Add swift tutorials for basic call, voip push and chat features with SDK 5.0
This commit is contained in:
parent
22df57e83d
commit
4a5d86e9aa
13
.gitignore
vendored
13
.gitignore
vendored
@ -7,7 +7,7 @@ java/.idea/modules.xml
|
||||
java/.idea/workspace.xml
|
||||
java/.idea/navEditor.xml
|
||||
java/.idea/assetWizardSettings.xml
|
||||
java/.DS_Store
|
||||
.DS_Store
|
||||
java/build
|
||||
java/captures
|
||||
java/.externalNativeBuild
|
||||
@ -26,9 +26,10 @@ AppPackages
|
||||
[Oo]bj/
|
||||
[Bb]in/
|
||||
|
||||
swift/HelloLinphone/Podfile.lock
|
||||
swift/HelloLinphone/Pods/
|
||||
swift/HelloLinphone/HelloLinphone.xcodeproj/project.xcworkspace/xcuserdata/
|
||||
swift/HelloLinphone/HelloLinphone.xcodeproj/xcuserdata/
|
||||
swift/HelloLinphone/HelloLinphone.xcworkspace/xcuserdata/
|
||||
ios/swift/*/Podfile.lock
|
||||
ios/swift/*/Pods/
|
||||
ios/swift/*/*.xcodeproj/project.xcworkspace/xcuserdata/
|
||||
ios/swift/*/*.xcodeproj/xcuserdata/
|
||||
ios/swift/*/*.xcworkspace/xcuserdata/
|
||||
ios/swift/*/build
|
||||
|
||||
|
424
ios/swift/0-Helloworld/Helloworld.xcodeproj/project.pbxproj
Normal file
424
ios/swift/0-Helloworld/Helloworld.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,424 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
663D8CDF26E8E35400EE487F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D8CDE26E8E35400EE487F /* AppDelegate.swift */; };
|
||||
663D8CE126E8E35400EE487F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D8CE026E8E35400EE487F /* SceneDelegate.swift */; };
|
||||
663D8CE326E8E35400EE487F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D8CE226E8E35400EE487F /* ContentView.swift */; };
|
||||
663D8CE526E8E35500EE487F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 663D8CE426E8E35500EE487F /* Assets.xcassets */; };
|
||||
663D8CE826E8E35500EE487F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 663D8CE726E8E35500EE487F /* Preview Assets.xcassets */; };
|
||||
663D8CEB26E8E35500EE487F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 663D8CE926E8E35500EE487F /* LaunchScreen.storyboard */; };
|
||||
663D8CF326E8E73700EE487F /* HelloworldTutorial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663D8CF226E8E73700EE487F /* HelloworldTutorial.swift */; };
|
||||
AE5DCE54FB07B00CDB39CF8C /* Pods_Helloworld.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 658B93FC56A6311767BE2F24 /* Pods_Helloworld.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1D8A919C73E1D36DB079968D /* Pods-Helloworld.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Helloworld.debug.xcconfig"; path = "Target Support Files/Pods-Helloworld/Pods-Helloworld.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
658B93FC56A6311767BE2F24 /* Pods_Helloworld.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Helloworld.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
663D8CDB26E8E35400EE487F /* Helloworld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Helloworld.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
663D8CDE26E8E35400EE487F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
663D8CE026E8E35400EE487F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
663D8CE226E8E35400EE487F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
663D8CE426E8E35500EE487F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
663D8CE726E8E35500EE487F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
663D8CEA26E8E35500EE487F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
663D8CEC26E8E35500EE487F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
663D8CF226E8E73700EE487F /* HelloworldTutorial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = HelloworldTutorial.swift; path = ../../../../Downloads/HelloworldTutorial.swift; sourceTree = "<group>"; };
|
||||
B14B29CDA5B52FB0218CB545 /* Pods-Helloworld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Helloworld.release.xcconfig"; path = "Target Support Files/Pods-Helloworld/Pods-Helloworld.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
663D8CD826E8E35400EE487F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
AE5DCE54FB07B00CDB39CF8C /* Pods_Helloworld.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
663D8CD226E8E35400EE487F = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
663D8CDD26E8E35400EE487F /* Helloworld */,
|
||||
663D8CDC26E8E35400EE487F /* Products */,
|
||||
FBA8E9BB676F4A0224467983 /* Pods */,
|
||||
930DDB069926306D8F86A1DF /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
663D8CDC26E8E35400EE487F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
663D8CDB26E8E35400EE487F /* Helloworld.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
663D8CDD26E8E35400EE487F /* Helloworld */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
663D8CDE26E8E35400EE487F /* AppDelegate.swift */,
|
||||
663D8CE026E8E35400EE487F /* SceneDelegate.swift */,
|
||||
663D8CE226E8E35400EE487F /* ContentView.swift */,
|
||||
663D8CE426E8E35500EE487F /* Assets.xcassets */,
|
||||
663D8CE926E8E35500EE487F /* LaunchScreen.storyboard */,
|
||||
663D8CEC26E8E35500EE487F /* Info.plist */,
|
||||
663D8CE626E8E35500EE487F /* Preview Content */,
|
||||
663D8CF226E8E73700EE487F /* HelloworldTutorial.swift */,
|
||||
);
|
||||
path = Helloworld;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
663D8CE626E8E35500EE487F /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
663D8CE726E8E35500EE487F /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
930DDB069926306D8F86A1DF /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
658B93FC56A6311767BE2F24 /* Pods_Helloworld.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FBA8E9BB676F4A0224467983 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1D8A919C73E1D36DB079968D /* Pods-Helloworld.debug.xcconfig */,
|
||||
B14B29CDA5B52FB0218CB545 /* Pods-Helloworld.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
663D8CDA26E8E35400EE487F /* Helloworld */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 663D8CEF26E8E35500EE487F /* Build configuration list for PBXNativeTarget "Helloworld" */;
|
||||
buildPhases = (
|
||||
65BF27D12FE9B5322F627C5F /* [CP] Check Pods Manifest.lock */,
|
||||
663D8CD726E8E35400EE487F /* Sources */,
|
||||
663D8CD826E8E35400EE487F /* Frameworks */,
|
||||
663D8CD926E8E35400EE487F /* Resources */,
|
||||
6D3F26BE93D3EC1C45D2BDAE /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Helloworld;
|
||||
productName = Helloworld;
|
||||
productReference = 663D8CDB26E8E35400EE487F /* Helloworld.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
663D8CD326E8E35400EE487F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1250;
|
||||
LastUpgradeCheck = 1250;
|
||||
TargetAttributes = {
|
||||
663D8CDA26E8E35400EE487F = {
|
||||
CreatedOnToolsVersion = 12.5.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 663D8CD626E8E35400EE487F /* Build configuration list for PBXProject "Helloworld" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 663D8CD226E8E35400EE487F;
|
||||
productRefGroup = 663D8CDC26E8E35400EE487F /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
663D8CDA26E8E35400EE487F /* Helloworld */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
663D8CD926E8E35400EE487F /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
663D8CEB26E8E35500EE487F /* LaunchScreen.storyboard in Resources */,
|
||||
663D8CE826E8E35500EE487F /* Preview Assets.xcassets in Resources */,
|
||||
663D8CE526E8E35500EE487F /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
65BF27D12FE9B5322F627C5F /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Helloworld-checkManifestLockResult.txt",
|
||||
);
|
||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6D3F26BE93D3EC1C45D2BDAE /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Helloworld/Pods-Helloworld-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Helloworld/Pods-Helloworld-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Helloworld/Pods-Helloworld-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
663D8CD726E8E35400EE487F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
663D8CDF26E8E35400EE487F /* AppDelegate.swift in Sources */,
|
||||
663D8CE126E8E35400EE487F /* SceneDelegate.swift in Sources */,
|
||||
663D8CE326E8E35400EE487F /* ContentView.swift in Sources */,
|
||||
663D8CF326E8E73700EE487F /* HelloworldTutorial.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
663D8CE926E8E35500EE487F /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
663D8CEA26E8E35500EE487F /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
663D8CED26E8E35500EE487F /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
663D8CEE26E8E35500EE487F /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
663D8CF026E8E35500EE487F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 1D8A919C73E1D36DB079968D /* Pods-Helloworld.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Helloworld/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = Helloworld/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.Helloworld;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
663D8CF126E8E35500EE487F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B14B29CDA5B52FB0218CB545 /* Pods-Helloworld.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Helloworld/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = Helloworld/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.Helloworld;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
663D8CD626E8E35400EE487F /* Build configuration list for PBXProject "Helloworld" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
663D8CED26E8E35500EE487F /* Debug */,
|
||||
663D8CEE26E8E35500EE487F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
663D8CEF26E8E35500EE487F /* Build configuration list for PBXNativeTarget "Helloworld" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
663D8CF026E8E35500EE487F /* Debug */,
|
||||
663D8CF126E8E35500EE487F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 663D8CD326E8E35400EE487F /* Project object */;
|
||||
}
|
@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:HelloLinphone.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -1,17 +1,17 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// HelloLinphone
|
||||
// Helloworld
|
||||
//
|
||||
// Created by Danmei Chen on 23/06/2020.
|
||||
// Copyright © 2020 belledonne. All rights reserved.
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
@main
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
|
||||
|
||||
@ObservedObject var tutorialContext = HelloworldTutorialContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
32
ios/swift/0-Helloworld/Helloworld/ContentView.swift
Normal file
32
ios/swift/0-Helloworld/Helloworld/ContentView.swift
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// HelloworldTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : HelloworldTutorialContext
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Hello World ! \nCore Version is \(tutorialContext.coreVersion)")
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: HelloworldTutorialContext())
|
||||
}
|
||||
}
|
62
ios/swift/0-Helloworld/Helloworld/Info.plist
Normal file
62
ios/swift/0-Helloworld/Helloworld/Info.plist
Normal file
@ -0,0 +1,62 @@
|
||||
<?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>$(DEVELOPMENT_LANGUAGE)</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>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -1,19 +1,16 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// HelloLinphone
|
||||
// Helloworld
|
||||
//
|
||||
// Created by Danmei Chen on 23/06/2020.
|
||||
// Copyright © 2020 belledonne. All rights reserved.
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import linphonesw
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
var mCore: Core!
|
||||
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
@ -21,23 +18,17 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
// Core is the main object of the SDK. You can't do much without it.
|
||||
// To create a Core, we need the instance of the Factory.
|
||||
let factory = Factory.Instance
|
||||
|
||||
// Your Core can use up to 2 configuration files, but that isn't mandatory.
|
||||
// On ios the Core doesn't need to have the application context to work.
|
||||
try? mCore = factory.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
|
||||
let delegate = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(coreVersion: Core.getVersion)
|
||||
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +36,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
24
ios/swift/0-Helloworld/Podfile
Normal file
24
ios/swift/0-Helloworld/Podfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
source "https://gitlab.linphone.org/BC/public/podspec.git"
|
||||
source "https://github.com/CocoaPods/Specs.git"
|
||||
|
||||
def basic_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '~> 5.0.0'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
target 'Helloworld' do
|
||||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for Helloworld
|
||||
basic_pods
|
||||
|
||||
end
|
8
ios/swift/0-Helloworld/README.md
Normal file
8
ios/swift/0-Helloworld/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
Hello World tutorial
|
||||
====================
|
||||
|
||||
The purpose of this tutorial is to explain how to add our SDK as a dependency of an Swift project and how to create the `Core` object that all our APIs depends on.
|
||||
|
||||
Start by taking a look at the `Podfile` file, and use the "pod install" command to create Helloworld.xcworkspace and build the app
|
||||
|
||||
The user interface will only display the `Core`'s version, but in the next tutorial you will learn how to use it to login your SIP account.
|
@ -3,141 +3,143 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
6109A53324A1FB600080B339 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6109A53224A1FB600080B339 /* AppDelegate.swift */; };
|
||||
6109A53524A1FB600080B339 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6109A53424A1FB600080B339 /* SceneDelegate.swift */; };
|
||||
6109A53724A1FB600080B339 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6109A53624A1FB600080B339 /* ContentView.swift */; };
|
||||
6109A53924A1FB610080B339 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6109A53824A1FB610080B339 /* Assets.xcassets */; };
|
||||
6109A53C24A1FB610080B339 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6109A53B24A1FB610080B339 /* Preview Assets.xcassets */; };
|
||||
6109A53F24A1FB610080B339 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6109A53D24A1FB610080B339 /* LaunchScreen.storyboard */; };
|
||||
77A49EE3C36F606277338500 /* Pods_HelloLinphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77C78D4B854746B756F138EC /* Pods_HelloLinphone.framework */; };
|
||||
43EDF804909F295D8FD16E72 /* Pods_LoginTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52A14DA7DC9DFF94D4A572CE /* Pods_LoginTutorial.framework */; };
|
||||
6604167924D4606A0064FC6C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604167824D4606A0064FC6C /* AppDelegate.swift */; };
|
||||
6604167B24D4606A0064FC6C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604167A24D4606A0064FC6C /* SceneDelegate.swift */; };
|
||||
6604167D24D4606A0064FC6C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604167C24D4606A0064FC6C /* ContentView.swift */; };
|
||||
6604167F24D4606B0064FC6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6604167E24D4606B0064FC6C /* Assets.xcassets */; };
|
||||
6604168224D4606B0064FC6C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6604168124D4606B0064FC6C /* Preview Assets.xcassets */; };
|
||||
6604168524D4606B0064FC6C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6604168324D4606B0064FC6C /* LaunchScreen.storyboard */; };
|
||||
6604168D24D4607A0064FC6C /* LoginTutorial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604168C24D4607A0064FC6C /* LoginTutorial.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
58D449155D749B90DECEF33F /* Pods-HelloLinphone.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloLinphone.debug.xcconfig"; path = "Target Support Files/Pods-HelloLinphone/Pods-HelloLinphone.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
6109A52F24A1FB600080B339 /* HelloLinphone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloLinphone.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6109A53224A1FB600080B339 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
6109A53424A1FB600080B339 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
6109A53624A1FB600080B339 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
6109A53824A1FB610080B339 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
6109A53B24A1FB610080B339 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
6109A53E24A1FB610080B339 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
6109A54024A1FB610080B339 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
77C78D4B854746B756F138EC /* Pods_HelloLinphone.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HelloLinphone.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CCABD171CB8B5F0B32B7C819 /* Pods-HelloLinphone.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloLinphone.release.xcconfig"; path = "Target Support Files/Pods-HelloLinphone/Pods-HelloLinphone.release.xcconfig"; sourceTree = "<group>"; };
|
||||
52A14DA7DC9DFF94D4A572CE /* Pods_LoginTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LoginTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6604167524D4606A0064FC6C /* LoginTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LoginTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6604167824D4606A0064FC6C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
6604167A24D4606A0064FC6C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
6604167C24D4606A0064FC6C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
6604167E24D4606B0064FC6C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
6604168124D4606B0064FC6C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
6604168424D4606B0064FC6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
6604168624D4606B0064FC6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
6604168C24D4607A0064FC6C /* LoginTutorial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginTutorial.swift; sourceTree = "<group>"; };
|
||||
86EBE739D84760246FCA17F1 /* Pods-LoginTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoginTutorial.debug.xcconfig"; path = "Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A3C6682B4C89F9C91835CCC0 /* Pods-LoginTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoginTutorial.release.xcconfig"; path = "Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
6109A52C24A1FB600080B339 /* Frameworks */ = {
|
||||
6604167224D4606A0064FC6C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
77A49EE3C36F606277338500 /* Pods_HelloLinphone.framework in Frameworks */,
|
||||
43EDF804909F295D8FD16E72 /* Pods_LoginTutorial.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
12F6903ABA1B6D98B920C503 /* Frameworks */ = {
|
||||
0A22ADFA8AED8923D454874F /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
77C78D4B854746B756F138EC /* Pods_HelloLinphone.framework */,
|
||||
86EBE739D84760246FCA17F1 /* Pods-LoginTutorial.debug.xcconfig */,
|
||||
A3C6682B4C89F9C91835CCC0 /* Pods-LoginTutorial.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3200FE58EDFCC48A3C66678D /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
52A14DA7DC9DFF94D4A572CE /* Pods_LoginTutorial.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6109A52624A1FB600080B339 = {
|
||||
6604166C24D4606A0064FC6C = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6109A53124A1FB600080B339 /* HelloLinphone */,
|
||||
6109A53024A1FB600080B339 /* Products */,
|
||||
7DEB177E8F89B4C059EAD432 /* Pods */,
|
||||
12F6903ABA1B6D98B920C503 /* Frameworks */,
|
||||
6604167724D4606A0064FC6C /* LoginTutorial */,
|
||||
6604167624D4606A0064FC6C /* Products */,
|
||||
0A22ADFA8AED8923D454874F /* Pods */,
|
||||
3200FE58EDFCC48A3C66678D /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6109A53024A1FB600080B339 /* Products */ = {
|
||||
6604167624D4606A0064FC6C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6109A52F24A1FB600080B339 /* HelloLinphone.app */,
|
||||
6604167524D4606A0064FC6C /* LoginTutorial.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6109A53124A1FB600080B339 /* HelloLinphone */ = {
|
||||
6604167724D4606A0064FC6C /* LoginTutorial */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6109A53224A1FB600080B339 /* AppDelegate.swift */,
|
||||
6109A53424A1FB600080B339 /* SceneDelegate.swift */,
|
||||
6109A53624A1FB600080B339 /* ContentView.swift */,
|
||||
6109A53824A1FB610080B339 /* Assets.xcassets */,
|
||||
6109A53D24A1FB610080B339 /* LaunchScreen.storyboard */,
|
||||
6109A54024A1FB610080B339 /* Info.plist */,
|
||||
6109A53A24A1FB610080B339 /* Preview Content */,
|
||||
6604167824D4606A0064FC6C /* AppDelegate.swift */,
|
||||
6604167A24D4606A0064FC6C /* SceneDelegate.swift */,
|
||||
6604168C24D4607A0064FC6C /* LoginTutorial.swift */,
|
||||
6604167C24D4606A0064FC6C /* ContentView.swift */,
|
||||
6604167E24D4606B0064FC6C /* Assets.xcassets */,
|
||||
6604168324D4606B0064FC6C /* LaunchScreen.storyboard */,
|
||||
6604168624D4606B0064FC6C /* Info.plist */,
|
||||
6604168024D4606B0064FC6C /* Preview Content */,
|
||||
);
|
||||
path = HelloLinphone;
|
||||
path = LoginTutorial;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6109A53A24A1FB610080B339 /* Preview Content */ = {
|
||||
6604168024D4606B0064FC6C /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6109A53B24A1FB610080B339 /* Preview Assets.xcassets */,
|
||||
6604168124D4606B0064FC6C /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7DEB177E8F89B4C059EAD432 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58D449155D749B90DECEF33F /* Pods-HelloLinphone.debug.xcconfig */,
|
||||
CCABD171CB8B5F0B32B7C819 /* Pods-HelloLinphone.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6109A52E24A1FB600080B339 /* HelloLinphone */ = {
|
||||
6604167424D4606A0064FC6C /* LoginTutorial */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6109A54324A1FB610080B339 /* Build configuration list for PBXNativeTarget "HelloLinphone" */;
|
||||
buildConfigurationList = 6604168924D4606B0064FC6C /* Build configuration list for PBXNativeTarget "LoginTutorial" */;
|
||||
buildPhases = (
|
||||
F68B6F6ACD48C202C8DC4322 /* [CP] Check Pods Manifest.lock */,
|
||||
6109A52B24A1FB600080B339 /* Sources */,
|
||||
6109A52C24A1FB600080B339 /* Frameworks */,
|
||||
6109A52D24A1FB600080B339 /* Resources */,
|
||||
724EF46BD0CBE3A1971D77D0 /* [CP] Embed Pods Frameworks */,
|
||||
4EF45A68E9E85663FD1A4EC6 /* [CP] Check Pods Manifest.lock */,
|
||||
6604167124D4606A0064FC6C /* Sources */,
|
||||
6604167224D4606A0064FC6C /* Frameworks */,
|
||||
6604167324D4606A0064FC6C /* Resources */,
|
||||
0131188DB5E696F536B36946 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = HelloLinphone;
|
||||
productName = HelloLinphone;
|
||||
productReference = 6109A52F24A1FB600080B339 /* HelloLinphone.app */;
|
||||
name = LoginTutorial;
|
||||
productName = LoginTutorial;
|
||||
productReference = 6604167524D4606A0064FC6C /* LoginTutorial.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
6109A52724A1FB600080B339 /* Project object */ = {
|
||||
6604166D24D4606A0064FC6C /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1150;
|
||||
LastUpgradeCheck = 1150;
|
||||
ORGANIZATIONNAME = belledonne;
|
||||
ORGANIZATIONNAME = BelledonneCommunications;
|
||||
TargetAttributes = {
|
||||
6109A52E24A1FB600080B339 = {
|
||||
6604167424D4606A0064FC6C = {
|
||||
CreatedOnToolsVersion = 11.5;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 6109A52A24A1FB600080B339 /* Build configuration list for PBXProject "HelloLinphone" */;
|
||||
buildConfigurationList = 6604167024D4606A0064FC6C /* Build configuration list for PBXProject "LoginTutorial" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
@ -145,48 +147,48 @@
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 6109A52624A1FB600080B339;
|
||||
productRefGroup = 6109A53024A1FB600080B339 /* Products */;
|
||||
mainGroup = 6604166C24D4606A0064FC6C;
|
||||
productRefGroup = 6604167624D4606A0064FC6C /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
6109A52E24A1FB600080B339 /* HelloLinphone */,
|
||||
6604167424D4606A0064FC6C /* LoginTutorial */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
6109A52D24A1FB600080B339 /* Resources */ = {
|
||||
6604167324D4606A0064FC6C /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6109A53F24A1FB610080B339 /* LaunchScreen.storyboard in Resources */,
|
||||
6109A53C24A1FB610080B339 /* Preview Assets.xcassets in Resources */,
|
||||
6109A53924A1FB610080B339 /* Assets.xcassets in Resources */,
|
||||
6604168524D4606B0064FC6C /* LaunchScreen.storyboard in Resources */,
|
||||
6604168224D4606B0064FC6C /* Preview Assets.xcassets in Resources */,
|
||||
6604167F24D4606B0064FC6C /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
724EF46BD0CBE3A1971D77D0 /* [CP] Embed Pods Frameworks */ = {
|
||||
0131188DB5E696F536B36946 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-HelloLinphone/Pods-HelloLinphone-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-HelloLinphone/Pods-HelloLinphone-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HelloLinphone/Pods-HelloLinphone-frameworks.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F68B6F6ACD48C202C8DC4322 /* [CP] Check Pods Manifest.lock */ = {
|
||||
4EF45A68E9E85663FD1A4EC6 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@ -201,7 +203,7 @@
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-HelloLinphone-checkManifestLockResult.txt",
|
||||
"$(DERIVED_FILE_DIR)/Pods-LoginTutorial-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
@ -211,23 +213,24 @@
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
6109A52B24A1FB600080B339 /* Sources */ = {
|
||||
6604167124D4606A0064FC6C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6109A53324A1FB600080B339 /* AppDelegate.swift in Sources */,
|
||||
6109A53524A1FB600080B339 /* SceneDelegate.swift in Sources */,
|
||||
6109A53724A1FB600080B339 /* ContentView.swift in Sources */,
|
||||
6604167924D4606A0064FC6C /* AppDelegate.swift in Sources */,
|
||||
6604167B24D4606A0064FC6C /* SceneDelegate.swift in Sources */,
|
||||
6604168D24D4607A0064FC6C /* LoginTutorial.swift in Sources */,
|
||||
6604167D24D4606A0064FC6C /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
6109A53D24A1FB610080B339 /* LaunchScreen.storyboard */ = {
|
||||
6604168324D4606B0064FC6C /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
6109A53E24A1FB610080B339 /* Base */,
|
||||
6604168424D4606B0064FC6C /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
@ -235,7 +238,7 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
6109A54124A1FB610080B339 /* Debug */ = {
|
||||
6604168724D4606B0064FC6C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
@ -295,7 +298,7 @@
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6109A54224A1FB610080B339 /* Release */ = {
|
||||
6604168824D4606B0064FC6C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
@ -349,42 +352,42 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6109A54424A1FB610080B339 /* Debug */ = {
|
||||
6604168A24D4606B0064FC6C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 58D449155D749B90DECEF33F /* Pods-HelloLinphone.debug.xcconfig */;
|
||||
baseConfigurationReference = 86EBE739D84760246FCA17F1 /* Pods-LoginTutorial.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"HelloLinphone/Preview Content\"";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"LoginTutorial/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = HelloLinphone/Info.plist;
|
||||
INFOPLIST_FILE = LoginTutorial/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = belledonne.HelloLinphone;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.LoginTutorial;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6109A54524A1FB610080B339 /* Release */ = {
|
||||
6604168B24D4606B0064FC6C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = CCABD171CB8B5F0B32B7C819 /* Pods-HelloLinphone.release.xcconfig */;
|
||||
baseConfigurationReference = A3C6682B4C89F9C91835CCC0 /* Pods-LoginTutorial.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"HelloLinphone/Preview Content\"";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"LoginTutorial/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = HelloLinphone/Info.plist;
|
||||
INFOPLIST_FILE = LoginTutorial/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = belledonne.HelloLinphone;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.LoginTutorial;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -394,25 +397,25 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
6109A52A24A1FB600080B339 /* Build configuration list for PBXProject "HelloLinphone" */ = {
|
||||
6604167024D4606A0064FC6C /* Build configuration list for PBXProject "LoginTutorial" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6109A54124A1FB610080B339 /* Debug */,
|
||||
6109A54224A1FB610080B339 /* Release */,
|
||||
6604168724D4606B0064FC6C /* Debug */,
|
||||
6604168824D4606B0064FC6C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6109A54324A1FB610080B339 /* Build configuration list for PBXNativeTarget "HelloLinphone" */ = {
|
||||
6604168924D4606B0064FC6C /* Build configuration list for PBXNativeTarget "LoginTutorial" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6109A54424A1FB610080B339 /* Debug */,
|
||||
6109A54524A1FB610080B339 /* Release */,
|
||||
6604168A24D4606B0064FC6C /* Debug */,
|
||||
6604168B24D4606B0064FC6C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 6109A52724A1FB600080B339 /* Project object */;
|
||||
rootObject = 6604166D24D4606A0064FC6C /* Project object */;
|
||||
}
|
7
ios/swift/1-LoginTutorial/LoginTutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/swift/1-LoginTutorial/LoginTutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:LoginTutorial.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
38
ios/swift/1-LoginTutorial/LoginTutorial/AppDelegate.swift
Normal file
38
ios/swift/1-LoginTutorial/LoginTutorial/AppDelegate.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@ObservedObject var tutorialContext = LoginTutorialContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
87
ios/swift/1-LoginTutorial/LoginTutorial/ContentView.swift
Normal file
87
ios/swift/1-LoginTutorial/LoginTutorial/ContentView.swift
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : LoginTutorialContext
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
HStack {
|
||||
Text("Username:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.username)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Password:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.passwd)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Domain:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.domain)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
Picker(selection: $tutorialContext.transportType, label: Text("Transport:")) {
|
||||
Text("TLS").tag("TLS")
|
||||
Text("TCP").tag("TCP")
|
||||
Text("UDP").tag("UDP")
|
||||
}.pickerStyle(SegmentedPickerStyle()).padding()
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.loggedIn)
|
||||
{
|
||||
self.tutorialContext.unregister()
|
||||
self.tutorialContext.delete()
|
||||
} else {
|
||||
self.tutorialContext.login()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text(tutorialContext.loggedIn ? "Log out & \ndelete account" : "Create & \nlog in account")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 220.0, height: 90)
|
||||
.background(Color.gray)
|
||||
}
|
||||
|
||||
}
|
||||
HStack {
|
||||
Text("Login State : ")
|
||||
.font(.footnote)
|
||||
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
|
||||
.font(.footnote)
|
||||
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
|
||||
}.padding(.top, 10.0)
|
||||
}
|
||||
}
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Core Version is \(tutorialContext.coreVersion)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: LoginTutorialContext())
|
||||
}
|
||||
}
|
128
ios/swift/1-LoginTutorial/LoginTutorial/LoginTutorial.swift
Normal file
128
ios/swift/1-LoginTutorial/LoginTutorial/LoginTutorial.swift
Normal file
@ -0,0 +1,128 @@
|
||||
//
|
||||
// LoginExample.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import linphonesw
|
||||
|
||||
class LoginTutorialContext : ObservableObject
|
||||
{
|
||||
var mCore: Core!
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
|
||||
/*------------ Login tutorial related variables -------*/
|
||||
var mRegistrationDelegate : CoreDelegate!
|
||||
@Published var username : String = "user"
|
||||
@Published var passwd : String = "pwd"
|
||||
@Published var domain : String = "sip.example.org"
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var transportType : String = "TLS"
|
||||
|
||||
init()
|
||||
{
|
||||
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
|
||||
try? mCore.start()
|
||||
|
||||
// Create a Core listener to listen for the callback we need
|
||||
// In this case, we want to know about the account registration status
|
||||
mRegistrationDelegate = CoreDelegateStub(onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
|
||||
// If account has been configured correctly, we will go through Progress and Ok states
|
||||
// Otherwise, we will be Failed.
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
mCore.addDelegate(delegate: mRegistrationDelegate)
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
do {
|
||||
// Get the transport protocol to use.
|
||||
// TLS is strongly recommended
|
||||
// Only use UDP if you don't have the choice
|
||||
var transport : TransportType
|
||||
if (transportType == "TLS") { transport = TransportType.Tls }
|
||||
else if (transportType == "TCP") { transport = TransportType.Tcp }
|
||||
else { transport = TransportType.Udp }
|
||||
|
||||
// To configure a SIP account, we need an Account object and an AuthInfo object
|
||||
// The first one is how to connect to the proxy server, the second one stores the credentials
|
||||
|
||||
// The auth info can be created from the Factory as it's only a data class
|
||||
// userID is set to null as it's the same as the username in our case
|
||||
// ha1 is set to null as we are using the clear text password. Upon first register, the hash will be computed automatically.
|
||||
// The realm will be determined automatically from the first register, as well as the algorithm
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
|
||||
// Account object replaces deprecated ProxyConfig object
|
||||
// Account object is configured through an AccountParams object that we can obtain from the Core
|
||||
let accountParams = try mCore.createAccountParams()
|
||||
|
||||
// A SIP account is identified by an identity address that we can construct from the username and domain
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try! accountParams.setIdentityaddress(newValue: identity)
|
||||
|
||||
// We also need to configure where the proxy server is located
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
|
||||
// We use the Address object to easily set the transport protocol
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
// And we ensure the account will start the registration process
|
||||
accountParams.registerEnabled = true
|
||||
|
||||
// Now that our AccountParams is configured, we can create the Account object
|
||||
let account = try mCore.createAccount(params: accountParams)
|
||||
|
||||
// Now let's add our objects to the Core
|
||||
mCore.addAuthInfo(info: authInfo)
|
||||
try mCore.addAccount(account: account)
|
||||
|
||||
// Also set the newly added account as default
|
||||
mCore.defaultAccount = account
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func unregister()
|
||||
{
|
||||
// Here we will disable the registration of our Account
|
||||
if let account = mCore.defaultAccount {
|
||||
|
||||
let params = account.params
|
||||
// Returned params object is const, so to make changes we first need to clone it
|
||||
let clonedParams = params?.clone()
|
||||
|
||||
// Now let's make our changes
|
||||
clonedParams?.registerEnabled = false
|
||||
|
||||
// And apply them
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
// To completely remove an Account
|
||||
if let account = mCore.defaultAccount {
|
||||
mCore.removeAccount(account: account)
|
||||
|
||||
// To remove all accounts use
|
||||
mCore.clearAccounts()
|
||||
|
||||
// Same for auth info
|
||||
mCore.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
65
ios/swift/1-LoginTutorial/LoginTutorial/SceneDelegate.swift
Normal file
65
ios/swift/1-LoginTutorial/LoginTutorial/SceneDelegate.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
let delegate = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
24
ios/swift/1-LoginTutorial/Podfile
Normal file
24
ios/swift/1-LoginTutorial/Podfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
source "https://gitlab.linphone.org/BC/public/podspec.git"
|
||||
source "https://github.com/CocoaPods/Specs.git"
|
||||
|
||||
def basic_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '~> 5.0.0'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
target 'LoginTutorial' do
|
||||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for LoginTutorial
|
||||
basic_pods
|
||||
|
||||
end
|
10
ios/swift/1-LoginTutorial/README.md
Normal file
10
ios/swift/1-LoginTutorial/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
Account login tutorial
|
||||
====================
|
||||
|
||||
Now that you have set up Linphone-SDK in a Swift project, let's start using it.
|
||||
|
||||
We will see how to login on a SIP server using the `Core` object instanciated in the previous tutorial. As always, you will have to start with a "Pod install" to generate the xcworkspace for this app.
|
||||
|
||||
If you don't have a SIP server yet, you can create an account for free using our [free SIP service](https://subscribe.linphone.org/).
|
||||
|
||||
Once you'll be logged-in, you'll be able to continue to the next tutorials to make calls and send messages.
|
424
ios/swift/2-IncomingCall/IncomingCall.xcodeproj/project.pbxproj
Normal file
424
ios/swift/2-IncomingCall/IncomingCall.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,424 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
203CAD3D220FB2AEDD1C2463 /* Pods_IncomingCall.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F200A240C9F5BF773AF9024 /* Pods_IncomingCall.framework */; };
|
||||
66BF265826E9FCC90048D176 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66BF265726E9FCC90048D176 /* AppDelegate.swift */; };
|
||||
66BF265A26E9FCC90048D176 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66BF265926E9FCC90048D176 /* SceneDelegate.swift */; };
|
||||
66BF265C26E9FCC90048D176 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66BF265B26E9FCC90048D176 /* ContentView.swift */; };
|
||||
66BF265E26E9FCD00048D176 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 66BF265D26E9FCD00048D176 /* Assets.xcassets */; };
|
||||
66BF266126E9FCD00048D176 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 66BF266026E9FCD00048D176 /* Preview Assets.xcassets */; };
|
||||
66BF266426E9FCD00048D176 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 66BF266226E9FCD00048D176 /* LaunchScreen.storyboard */; };
|
||||
66BF266C26EA003C0048D176 /* IncomingCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66BF266B26EA003C0048D176 /* IncomingCall.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1F200A240C9F5BF773AF9024 /* Pods_IncomingCall.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IncomingCall.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4B0753133024A1C67E84CE1C /* Pods-IncomingCall.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IncomingCall.debug.xcconfig"; path = "Target Support Files/Pods-IncomingCall/Pods-IncomingCall.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
4B835D0562384FC441266A58 /* Pods-IncomingCall.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IncomingCall.release.xcconfig"; path = "Target Support Files/Pods-IncomingCall/Pods-IncomingCall.release.xcconfig"; sourceTree = "<group>"; };
|
||||
66BF265426E9FCC90048D176 /* IncomingCall.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IncomingCall.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
66BF265726E9FCC90048D176 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
66BF265926E9FCC90048D176 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
66BF265B26E9FCC90048D176 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
66BF265D26E9FCD00048D176 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
66BF266026E9FCD00048D176 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
66BF266326E9FCD00048D176 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
66BF266526E9FCD00048D176 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
66BF266B26EA003C0048D176 /* IncomingCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IncomingCall.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
66BF265126E9FCC90048D176 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
203CAD3D220FB2AEDD1C2463 /* Pods_IncomingCall.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
521BEF3D6EE06929A69119A3 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1F200A240C9F5BF773AF9024 /* Pods_IncomingCall.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
66BF264B26E9FCC90048D176 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
66BF265626E9FCC90048D176 /* IncomingCall */,
|
||||
66BF265526E9FCC90048D176 /* Products */,
|
||||
8ED5175BFA4F710BD04F20C6 /* Pods */,
|
||||
521BEF3D6EE06929A69119A3 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
66BF265526E9FCC90048D176 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
66BF265426E9FCC90048D176 /* IncomingCall.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
66BF265626E9FCC90048D176 /* IncomingCall */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
66BF265726E9FCC90048D176 /* AppDelegate.swift */,
|
||||
66BF265926E9FCC90048D176 /* SceneDelegate.swift */,
|
||||
66BF265B26E9FCC90048D176 /* ContentView.swift */,
|
||||
66BF265D26E9FCD00048D176 /* Assets.xcassets */,
|
||||
66BF266226E9FCD00048D176 /* LaunchScreen.storyboard */,
|
||||
66BF266526E9FCD00048D176 /* Info.plist */,
|
||||
66BF266B26EA003C0048D176 /* IncomingCall.swift */,
|
||||
66BF265F26E9FCD00048D176 /* Preview Content */,
|
||||
);
|
||||
path = IncomingCall;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
66BF265F26E9FCD00048D176 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
66BF266026E9FCD00048D176 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8ED5175BFA4F710BD04F20C6 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B0753133024A1C67E84CE1C /* Pods-IncomingCall.debug.xcconfig */,
|
||||
4B835D0562384FC441266A58 /* Pods-IncomingCall.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
66BF265326E9FCC90048D176 /* IncomingCall */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 66BF266826E9FCD00048D176 /* Build configuration list for PBXNativeTarget "IncomingCall" */;
|
||||
buildPhases = (
|
||||
1A16B6EAABD03BDFB6DDFABD /* [CP] Check Pods Manifest.lock */,
|
||||
66BF265026E9FCC90048D176 /* Sources */,
|
||||
66BF265126E9FCC90048D176 /* Frameworks */,
|
||||
66BF265226E9FCC90048D176 /* Resources */,
|
||||
37BA1CF9C1962947CFE3234B /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = IncomingCall;
|
||||
productName = IncomingCall;
|
||||
productReference = 66BF265426E9FCC90048D176 /* IncomingCall.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
66BF264C26E9FCC90048D176 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1250;
|
||||
LastUpgradeCheck = 1250;
|
||||
TargetAttributes = {
|
||||
66BF265326E9FCC90048D176 = {
|
||||
CreatedOnToolsVersion = 12.5.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 66BF264F26E9FCC90048D176 /* Build configuration list for PBXProject "IncomingCall" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 66BF264B26E9FCC90048D176;
|
||||
productRefGroup = 66BF265526E9FCC90048D176 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
66BF265326E9FCC90048D176 /* IncomingCall */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
66BF265226E9FCC90048D176 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
66BF266426E9FCD00048D176 /* LaunchScreen.storyboard in Resources */,
|
||||
66BF266126E9FCD00048D176 /* Preview Assets.xcassets in Resources */,
|
||||
66BF265E26E9FCD00048D176 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
1A16B6EAABD03BDFB6DDFABD /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-IncomingCall-checkManifestLockResult.txt",
|
||||
);
|
||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
37BA1CF9C1962947CFE3234B /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-IncomingCall/Pods-IncomingCall-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-IncomingCall/Pods-IncomingCall-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-IncomingCall/Pods-IncomingCall-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
66BF265026E9FCC90048D176 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
66BF265826E9FCC90048D176 /* AppDelegate.swift in Sources */,
|
||||
66BF266C26EA003C0048D176 /* IncomingCall.swift in Sources */,
|
||||
66BF265A26E9FCC90048D176 /* SceneDelegate.swift in Sources */,
|
||||
66BF265C26E9FCC90048D176 /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
66BF266226E9FCD00048D176 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
66BF266326E9FCD00048D176 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
66BF266626E9FCD00048D176 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
66BF266726E9FCD00048D176 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
66BF266926E9FCD00048D176 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 4B0753133024A1C67E84CE1C /* Pods-IncomingCall.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"IncomingCall/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = IncomingCall/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.IncomingCall;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
66BF266A26E9FCD00048D176 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 4B835D0562384FC441266A58 /* Pods-IncomingCall.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"IncomingCall/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = IncomingCall/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.IncomingCall;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
66BF264F26E9FCC90048D176 /* Build configuration list for PBXProject "IncomingCall" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
66BF266626E9FCD00048D176 /* Debug */,
|
||||
66BF266726E9FCD00048D176 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
66BF266826E9FCD00048D176 /* Build configuration list for PBXNativeTarget "IncomingCall" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
66BF266926E9FCD00048D176 /* Debug */,
|
||||
66BF266A26E9FCD00048D176 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 66BF264C26E9FCC90048D176 /* Project object */;
|
||||
}
|
7
ios/swift/2-IncomingCall/IncomingCall.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/swift/2-IncomingCall/IncomingCall.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,8 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
38
ios/swift/2-IncomingCall/IncomingCall/AppDelegate.swift
Normal file
38
ios/swift/2-IncomingCall/IncomingCall/AppDelegate.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@ObservedObject var tutorialContext = IncomingCallTutorialContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
149
ios/swift/2-IncomingCall/IncomingCall/ContentView.swift
Normal file
149
ios/swift/2-IncomingCall/IncomingCall/ContentView.swift
Normal file
@ -0,0 +1,149 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// IncomingCall tutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 09/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : IncomingCallTutorialContext
|
||||
|
||||
func callStateString() -> String {
|
||||
if (tutorialContext.isCallRunning) {
|
||||
return "Call running"
|
||||
} else if (tutorialContext.isCallIncoming) {
|
||||
return "Incoming call"
|
||||
} else {
|
||||
return "No Call"
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
HStack {
|
||||
Text("Username:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.username)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Password:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.passwd)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Domain:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.domain)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
Picker(selection: $tutorialContext.transportType, label: Text("Transport:")) {
|
||||
Text("TLS").tag("TLS")
|
||||
Text("TCP").tag("TCP")
|
||||
Text("UDP").tag("UDP")
|
||||
}.pickerStyle(SegmentedPickerStyle()).padding()
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.loggedIn)
|
||||
{
|
||||
self.tutorialContext.unregister()
|
||||
self.tutorialContext.delete()
|
||||
} else {
|
||||
self.tutorialContext.login()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text(tutorialContext.loggedIn ? "Log out & \ndelete account" : "Create & \nlog in account")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 220.0, height: 90)
|
||||
.background(Color.gray)
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Text("Login State : ")
|
||||
.font(.footnote)
|
||||
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
|
||||
.font(.footnote)
|
||||
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
|
||||
}.padding(.top, 10.0)
|
||||
}
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.isCallIncoming) {
|
||||
self.tutorialContext.acceptCall()
|
||||
} else if (self.tutorialContext.isCallRunning){
|
||||
self.tutorialContext.terminateCall()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text( (tutorialContext.isCallRunning) ? "Terminate" : "Accept")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 180.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
.disabled(!tutorialContext.isCallIncoming && !tutorialContext.isCallRunning)
|
||||
HStack {
|
||||
Text(callStateString()).italic()
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Text("Caller:").font(.title).underline()
|
||||
Text(tutorialContext.remoteAddress)
|
||||
Spacer()
|
||||
}.padding(.top, 5)
|
||||
HStack {
|
||||
Text("Call msg:").font(.title3).underline()
|
||||
Text(tutorialContext.callMsg)
|
||||
Spacer()
|
||||
}.padding(.top, 5)
|
||||
HStack {
|
||||
Button(action: tutorialContext.toggleSpeaker)
|
||||
{
|
||||
Text((tutorialContext.isSpeakerEnabled) ? "Speaker OFF" : "Speaker ON")
|
||||
.font(.title3)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 140.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
.disabled(!tutorialContext.isCallRunning)
|
||||
Button(action: tutorialContext.muteMicrophone)
|
||||
{
|
||||
Text((tutorialContext.isMicrophoneEnabled) ? "Microphone OFF" : "Microphone ON")
|
||||
.font(.title3)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 160.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
.disabled(!tutorialContext.isCallRunning)
|
||||
}.padding(.top, 10)
|
||||
}.padding(.top, 30)
|
||||
}
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Core Version is \(tutorialContext.coreVersion)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: IncomingCallTutorialContext())
|
||||
}
|
||||
}
|
162
ios/swift/2-IncomingCall/IncomingCall/IncomingCall.swift
Normal file
162
ios/swift/2-IncomingCall/IncomingCall/IncomingCall.swift
Normal file
@ -0,0 +1,162 @@
|
||||
//
|
||||
// IncomingCall.swift
|
||||
// IncomingCall tutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import linphonesw
|
||||
|
||||
class IncomingCallTutorialContext : ObservableObject
|
||||
{
|
||||
var mCore: Core!
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
|
||||
var mAccount: Account?
|
||||
var mCoreDelegate : CoreDelegate!
|
||||
@Published var username : String = "user"
|
||||
@Published var passwd : String = "pwd"
|
||||
@Published var domain : String = "sip.example.org"
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var transportType : String = "TLS"
|
||||
|
||||
// Incoming call related variables
|
||||
@Published var callMsg : String = ""
|
||||
@Published var isCallIncoming : Bool = false
|
||||
@Published var isCallRunning : Bool = false
|
||||
@Published var remoteAddress : String = "Nobody yet"
|
||||
@Published var isSpeakerEnabled : Bool = false
|
||||
@Published var isMicrophoneEnabled : Bool = false
|
||||
|
||||
init()
|
||||
{
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
|
||||
try? mCore.start()
|
||||
|
||||
mCoreDelegate = CoreDelegateStub( onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||
self.callMsg = message
|
||||
if (state == .IncomingReceived) { // When a call is received
|
||||
self.isCallIncoming = true
|
||||
self.isCallRunning = false
|
||||
self.remoteAddress = call.remoteAddress!.asStringUriOnly()
|
||||
} else if (state == .Connected) { // When a call is over
|
||||
self.isCallIncoming = false
|
||||
self.isCallRunning = true
|
||||
} else if (state == .Released) { // When a call is over
|
||||
self.isCallIncoming = false
|
||||
self.isCallRunning = false
|
||||
self.remoteAddress = "Nobody yet"
|
||||
}
|
||||
}, onAudioDeviceChanged: { (core: Core, device: AudioDevice) in
|
||||
// This callback will be triggered when a successful audio device has been changed
|
||||
}, onAudioDevicesListUpdated: { (core: Core) in
|
||||
// This callback will be triggered when the available devices list has changed,
|
||||
// for example after a bluetooth headset has been connected/disconnected.
|
||||
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
mCore.addDelegate(delegate: mCoreDelegate)
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
do {
|
||||
var transport : TransportType
|
||||
if (transportType == "TLS") { transport = TransportType.Tls }
|
||||
else if (transportType == "TCP") { transport = TransportType.Tcp }
|
||||
else { transport = TransportType.Udp }
|
||||
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
let accountParams = try mCore.createAccountParams()
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try! accountParams.setIdentityaddress(newValue: identity)
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
accountParams.registerEnabled = true
|
||||
mAccount = try mCore.createAccount(params: accountParams)
|
||||
mCore.addAuthInfo(info: authInfo)
|
||||
try mCore.addAccount(account: mAccount!)
|
||||
mCore.defaultAccount = mAccount
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func unregister()
|
||||
{
|
||||
if let account = mCore.defaultAccount {
|
||||
let params = account.params
|
||||
let clonedParams = params?.clone()
|
||||
clonedParams?.registerEnabled = false
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
if let account = mCore.defaultAccount {
|
||||
mCore.removeAccount(account: account)
|
||||
mCore.clearAccounts()
|
||||
mCore.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
|
||||
func terminateCall() {
|
||||
do {
|
||||
// Terminates the call, whether it is ringing or running
|
||||
try mCore.currentCall?.terminate()
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func acceptCall() {
|
||||
// IMPORTANT : Make sure you allowed the use of the microphone (see key "Privacy - Microphone usage description" in Info.plist) !
|
||||
do {
|
||||
// if we wanted, we could create a CallParams object
|
||||
// and answer using this object to make changes to the call configuration
|
||||
// (see OutgoingCall tutorial)
|
||||
try mCore.currentCall?.accept()
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func muteMicrophone() {
|
||||
// The following toggles the microphone, disabling completely / enabling the sound capture
|
||||
// from the device microphone
|
||||
mCore.micEnabled = !mCore.micEnabled
|
||||
isMicrophoneEnabled = !isMicrophoneEnabled
|
||||
}
|
||||
|
||||
func toggleSpeaker() {
|
||||
// Get the currently used audio device
|
||||
let currentAudioDevice = mCore.currentCall?.outputAudioDevice
|
||||
let speakerEnabled = currentAudioDevice?.type == AudioDeviceType.Speaker
|
||||
|
||||
let test = currentAudioDevice?.deviceName
|
||||
// We can get a list of all available audio devices using
|
||||
// Note that on tablets for example, there may be no Earpiece device
|
||||
for audioDevice in mCore.audioDevices {
|
||||
|
||||
// For IOS, the Speaker is an exception, Linphone cannot differentiate Input and Output.
|
||||
// This means that the default output device, the earpiece, is paired with the default phone microphone.
|
||||
// Setting the output audio device to the microphone will redirect the sound to the earpiece.
|
||||
if (speakerEnabled && audioDevice.type == AudioDeviceType.Microphone) {
|
||||
mCore.currentCall?.outputAudioDevice = audioDevice
|
||||
isSpeakerEnabled = false
|
||||
return
|
||||
} else if (!speakerEnabled && audioDevice.type == AudioDeviceType.Speaker) {
|
||||
mCore.currentCall?.outputAudioDevice = audioDevice
|
||||
isSpeakerEnabled = true
|
||||
return
|
||||
}
|
||||
/* If we wanted to route the audio to a bluetooth headset
|
||||
else if (audioDevice.type == AudioDevice.Type.Bluetooth) {
|
||||
core.currentCall?.outputAudioDevice = audioDevice
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
64
ios/swift/2-IncomingCall/IncomingCall/Info.plist
Normal file
64
ios/swift/2-IncomingCall/IncomingCall/Info.plist
Normal file
@ -0,0 +1,64 @@
|
||||
<?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>NSMicrophoneUsageDescription</key>
|
||||
<string>Microphone access</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</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>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
65
ios/swift/2-IncomingCall/IncomingCall/SceneDelegate.swift
Normal file
65
ios/swift/2-IncomingCall/IncomingCall/SceneDelegate.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
let delegate = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
24
ios/swift/2-IncomingCall/Podfile
Normal file
24
ios/swift/2-IncomingCall/Podfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
source "https://gitlab.linphone.org/BC/public/podspec.git"
|
||||
source "https://github.com/CocoaPods/Specs.git"
|
||||
|
||||
def basic_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '~> 5.0.0'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
target 'IncomingCall' do
|
||||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for IncomingCall
|
||||
basic_pods
|
||||
|
||||
end
|
10
ios/swift/2-IncomingCall/README.md
Normal file
10
ios/swift/2-IncomingCall/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
Incoming call tutorial
|
||||
====================
|
||||
|
||||
This tutorial will focus on how the app will be notified when a call is being received and how to either accept it or terminate it.
|
||||
|
||||
We'll also cover how to toggle the microphone and the speakerphone during an active call.
|
||||
|
||||
If you want to test it on either a device or an emulator, you'll need another SIP client to make the call. If you don't, you can use the [outgoing call tutorial](https://gitlab.linphone.org/BC/public/tutorials/-/tree/master/ios/swift/3-OutgoingCall) to do it.
|
||||
|
||||
Note that changes to the "info.plist" file were made to enable the iphone microphone
|
424
ios/swift/3-OutgoingCall/OutgoingCall.xcodeproj/project.pbxproj
Normal file
424
ios/swift/3-OutgoingCall/OutgoingCall.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,424 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
664BC0C126EA4E6D007EE298 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0C026EA4E6D007EE298 /* AppDelegate.swift */; };
|
||||
664BC0C326EA4E6D007EE298 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0C226EA4E6D007EE298 /* SceneDelegate.swift */; };
|
||||
664BC0C526EA4E6D007EE298 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0C426EA4E6D007EE298 /* ContentView.swift */; };
|
||||
664BC0C726EA4E6E007EE298 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664BC0C626EA4E6E007EE298 /* Assets.xcassets */; };
|
||||
664BC0CA26EA4E6E007EE298 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664BC0C926EA4E6E007EE298 /* Preview Assets.xcassets */; };
|
||||
664BC0CD26EA4E6E007EE298 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 664BC0CB26EA4E6E007EE298 /* LaunchScreen.storyboard */; };
|
||||
664BC0D526EA5B2E007EE298 /* OutgoingCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0D426EA5B2E007EE298 /* OutgoingCall.swift */; };
|
||||
CCE49B664A0761B2077AA237 /* Pods_OutgoingCall.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E3E7DFC01F4CC7F8D82420D /* Pods_OutgoingCall.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0E3E7DFC01F4CC7F8D82420D /* Pods_OutgoingCall.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OutgoingCall.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4F69E3A4EB1062C38B03A5BE /* Pods-OutgoingCall.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OutgoingCall.debug.xcconfig"; path = "Target Support Files/Pods-OutgoingCall/Pods-OutgoingCall.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
664BC0BD26EA4E6D007EE298 /* OutgoingCall.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OutgoingCall.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
664BC0C026EA4E6D007EE298 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
664BC0C226EA4E6D007EE298 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
664BC0C426EA4E6D007EE298 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
664BC0C626EA4E6E007EE298 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
664BC0C926EA4E6E007EE298 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
664BC0CC26EA4E6E007EE298 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
664BC0CE26EA4E6E007EE298 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
664BC0D426EA5B2E007EE298 /* OutgoingCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingCall.swift; sourceTree = "<group>"; };
|
||||
673A75DA326F185877FA9965 /* Pods-OutgoingCall.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OutgoingCall.release.xcconfig"; path = "Target Support Files/Pods-OutgoingCall/Pods-OutgoingCall.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
664BC0BA26EA4E6D007EE298 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CCE49B664A0761B2077AA237 /* Pods_OutgoingCall.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
011FA7818C38DEF3B6BB2C74 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0E3E7DFC01F4CC7F8D82420D /* Pods_OutgoingCall.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0B426EA4E6D007EE298 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0BF26EA4E6D007EE298 /* OutgoingCall */,
|
||||
664BC0BE26EA4E6D007EE298 /* Products */,
|
||||
740448E44E890F2FA8682B0B /* Pods */,
|
||||
011FA7818C38DEF3B6BB2C74 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0BE26EA4E6D007EE298 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0BD26EA4E6D007EE298 /* OutgoingCall.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0BF26EA4E6D007EE298 /* OutgoingCall */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0C026EA4E6D007EE298 /* AppDelegate.swift */,
|
||||
664BC0C226EA4E6D007EE298 /* SceneDelegate.swift */,
|
||||
664BC0C426EA4E6D007EE298 /* ContentView.swift */,
|
||||
664BC0C626EA4E6E007EE298 /* Assets.xcassets */,
|
||||
664BC0CB26EA4E6E007EE298 /* LaunchScreen.storyboard */,
|
||||
664BC0CE26EA4E6E007EE298 /* Info.plist */,
|
||||
664BC0D426EA5B2E007EE298 /* OutgoingCall.swift */,
|
||||
664BC0C826EA4E6E007EE298 /* Preview Content */,
|
||||
);
|
||||
path = OutgoingCall;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0C826EA4E6E007EE298 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0C926EA4E6E007EE298 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
740448E44E890F2FA8682B0B /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4F69E3A4EB1062C38B03A5BE /* Pods-OutgoingCall.debug.xcconfig */,
|
||||
673A75DA326F185877FA9965 /* Pods-OutgoingCall.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
664BC0BC26EA4E6D007EE298 /* OutgoingCall */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 664BC0D126EA4E6E007EE298 /* Build configuration list for PBXNativeTarget "OutgoingCall" */;
|
||||
buildPhases = (
|
||||
A67E5FDCF316693C4106D5EC /* [CP] Check Pods Manifest.lock */,
|
||||
664BC0B926EA4E6D007EE298 /* Sources */,
|
||||
664BC0BA26EA4E6D007EE298 /* Frameworks */,
|
||||
664BC0BB26EA4E6D007EE298 /* Resources */,
|
||||
71824FDC693517F29C1C5E13 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = OutgoingCall;
|
||||
productName = OutgoingCall;
|
||||
productReference = 664BC0BD26EA4E6D007EE298 /* OutgoingCall.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
664BC0B526EA4E6D007EE298 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1250;
|
||||
LastUpgradeCheck = 1250;
|
||||
TargetAttributes = {
|
||||
664BC0BC26EA4E6D007EE298 = {
|
||||
CreatedOnToolsVersion = 12.5.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 664BC0B826EA4E6D007EE298 /* Build configuration list for PBXProject "OutgoingCall" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 664BC0B426EA4E6D007EE298;
|
||||
productRefGroup = 664BC0BE26EA4E6D007EE298 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
664BC0BC26EA4E6D007EE298 /* OutgoingCall */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
664BC0BB26EA4E6D007EE298 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
664BC0CD26EA4E6E007EE298 /* LaunchScreen.storyboard in Resources */,
|
||||
664BC0CA26EA4E6E007EE298 /* Preview Assets.xcassets in Resources */,
|
||||
664BC0C726EA4E6E007EE298 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
71824FDC693517F29C1C5E13 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-OutgoingCall/Pods-OutgoingCall-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-OutgoingCall/Pods-OutgoingCall-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OutgoingCall/Pods-OutgoingCall-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A67E5FDCF316693C4106D5EC /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-OutgoingCall-checkManifestLockResult.txt",
|
||||
);
|
||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
664BC0B926EA4E6D007EE298 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
664BC0C126EA4E6D007EE298 /* AppDelegate.swift in Sources */,
|
||||
664BC0D526EA5B2E007EE298 /* OutgoingCall.swift in Sources */,
|
||||
664BC0C326EA4E6D007EE298 /* SceneDelegate.swift in Sources */,
|
||||
664BC0C526EA4E6D007EE298 /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
664BC0CB26EA4E6E007EE298 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
664BC0CC26EA4E6E007EE298 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
664BC0CF26EA4E6E007EE298 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
664BC0D026EA4E6E007EE298 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
664BC0D226EA4E6E007EE298 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 4F69E3A4EB1062C38B03A5BE /* Pods-OutgoingCall.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"OutgoingCall/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = OutgoingCall/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.OutgoingCall;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
664BC0D326EA4E6E007EE298 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 673A75DA326F185877FA9965 /* Pods-OutgoingCall.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"OutgoingCall/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = OutgoingCall/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.OutgoingCall;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
664BC0B826EA4E6D007EE298 /* Build configuration list for PBXProject "OutgoingCall" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
664BC0CF26EA4E6E007EE298 /* Debug */,
|
||||
664BC0D026EA4E6E007EE298 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
664BC0D126EA4E6E007EE298 /* Build configuration list for PBXNativeTarget "OutgoingCall" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
664BC0D226EA4E6E007EE298 /* Debug */,
|
||||
664BC0D326EA4E6E007EE298 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 664BC0B526EA4E6D007EE298 /* Project object */;
|
||||
}
|
7
ios/swift/3-OutgoingCall/OutgoingCall.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/swift/3-OutgoingCall/OutgoingCall.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,8 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
38
ios/swift/3-OutgoingCall/OutgoingCall/AppDelegate.swift
Normal file
38
ios/swift/3-OutgoingCall/OutgoingCall/AppDelegate.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@ObservedObject var tutorialContext = OutgoingCallTutorialContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
171
ios/swift/3-OutgoingCall/OutgoingCall/ContentView.swift
Normal file
171
ios/swift/3-OutgoingCall/OutgoingCall/ContentView.swift
Normal file
@ -0,0 +1,171 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// IncomingCall tutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 09/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import linphonesw
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : OutgoingCallTutorialContext
|
||||
|
||||
func callStateString() -> String {
|
||||
if (tutorialContext.isCallRunning) {
|
||||
return "Call running"
|
||||
} else {
|
||||
return "No Call"
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
HStack {
|
||||
Text("Username:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.username)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Password:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.passwd)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Domain:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.domain)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
Picker(selection: $tutorialContext.transportType, label: Text("Transport:")) {
|
||||
Text("TLS").tag("TLS")
|
||||
Text("TCP").tag("TCP")
|
||||
Text("UDP").tag("UDP")
|
||||
}.pickerStyle(SegmentedPickerStyle()).padding()
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.loggedIn)
|
||||
{
|
||||
self.tutorialContext.unregister()
|
||||
self.tutorialContext.delete()
|
||||
} else {
|
||||
self.tutorialContext.login()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text(tutorialContext.loggedIn ? "Log out & \ndelete account" : "Create & \nlog in account")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 220.0, height: 90)
|
||||
.background(Color.gray)
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Text("Login State : ")
|
||||
.font(.footnote)
|
||||
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
|
||||
.font(.footnote)
|
||||
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
|
||||
}.padding(.top, 10.0)
|
||||
}
|
||||
VStack {
|
||||
HStack {
|
||||
Text("Call dest:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.remoteAddress)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(!tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.isCallRunning) {
|
||||
self.tutorialContext.terminateCall()
|
||||
} else {
|
||||
self.tutorialContext.outgoingCall()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text( (tutorialContext.isCallRunning) ? "End" : "Call")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 180.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
HStack {
|
||||
Text(tutorialContext.isCallRunning ? "Running" : "")
|
||||
.italic().foregroundColor(.green)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Text("Call msg:").font(.title3).underline()
|
||||
Text(tutorialContext.callMsg)
|
||||
Spacer()
|
||||
}.padding(.top, 5)
|
||||
HStack {
|
||||
Button(action: tutorialContext.toggleVideo)
|
||||
{
|
||||
Text((tutorialContext.isVideoEnabled) ? "Video OFF" : "Video ON")
|
||||
.font(.title3)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 130.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
.disabled(!tutorialContext.isCallRunning)
|
||||
Button(action: tutorialContext.toggleCamera)
|
||||
{
|
||||
Text("Change camera")
|
||||
.font(.title3)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 160.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
.disabled(!tutorialContext.canChangeCamera || !tutorialContext.isVideoEnabled)
|
||||
}.padding(.top, 5)
|
||||
HStack {
|
||||
VStack {
|
||||
LinphoneVideoViewHolder() { view in
|
||||
self.tutorialContext.mCore.nativeVideoWindow = view
|
||||
}
|
||||
.frame(width: 120, height: 160.0)
|
||||
.border(Color.gray)
|
||||
.padding(.leading)
|
||||
Text("What I receive")
|
||||
}
|
||||
Spacer()
|
||||
VStack {
|
||||
LinphoneVideoViewHolder() { view in
|
||||
self.tutorialContext.mCore.nativePreviewWindow = view
|
||||
}
|
||||
.frame(width: 120, height: 160.0)
|
||||
.border(Color.gray)
|
||||
.padding(.leading)
|
||||
Text("What I send")
|
||||
}
|
||||
}
|
||||
}.padding(.top, 30)
|
||||
}
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Core Version is \(tutorialContext.coreVersion)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: OutgoingCallTutorialContext())
|
||||
}
|
||||
}
|
66
ios/swift/3-OutgoingCall/OutgoingCall/Info.plist
Normal file
66
ios/swift/3-OutgoingCall/OutgoingCall/Info.plist
Normal file
@ -0,0 +1,66 @@
|
||||
<?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>NSCameraUsageDescription</key>
|
||||
<string>Cameras access</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Microphone access</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</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>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
238
ios/swift/3-OutgoingCall/OutgoingCall/OutgoingCall.swift
Normal file
238
ios/swift/3-OutgoingCall/OutgoingCall/OutgoingCall.swift
Normal file
@ -0,0 +1,238 @@
|
||||
//
|
||||
// OutgoingCall.swift
|
||||
// OutgoingCall tutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import linphonesw
|
||||
|
||||
class OutgoingCallTutorialContext : ObservableObject
|
||||
{
|
||||
var mCore: Core!
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
|
||||
var mAccount: Account?
|
||||
var mCoreDelegate : CoreDelegate!
|
||||
@Published var username : String = "user"
|
||||
@Published var passwd : String = "pwd"
|
||||
@Published var domain : String = "sip.example.org"
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var transportType : String = "TLS"
|
||||
|
||||
// Outgoing call related variables
|
||||
@Published var callMsg : String = ""
|
||||
@Published var isCallRunning : Bool = false
|
||||
@Published var isVideoEnabled : Bool = false
|
||||
@Published var canChangeCamera : Bool = false
|
||||
@Published var remoteAddress : String = "sip:arguillq@sip.linphone.org"
|
||||
|
||||
init()
|
||||
{
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
|
||||
// Here we enable the video capture & display at Core level
|
||||
// It doesn't mean calls will be made with video automatically,
|
||||
// But it allows to use it later
|
||||
mCore.videoCaptureEnabled = true
|
||||
mCore.videoDisplayEnabled = true
|
||||
|
||||
// When enabling the video, the remote will either automatically answer the update request
|
||||
// or it will ask it's user depending on it's policy.
|
||||
// Here we have configured the policy to always automatically accept video requests
|
||||
mCore.videoActivationPolicy!.automaticallyAccept = true
|
||||
// If you don't want to automatically accept,
|
||||
// you'll have to use a code similar to the one in toggleVideo to answer a received request
|
||||
|
||||
|
||||
// If the following property is enabled, it will automatically configure created call params with video enabled
|
||||
//core.videoActivationPolicy.automaticallyInitiate = true
|
||||
|
||||
try? mCore.start()
|
||||
|
||||
mCoreDelegate = CoreDelegateStub( onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||
// This function will be called each time a call state changes,
|
||||
// which includes new incoming/outgoing calls
|
||||
self.callMsg = message
|
||||
|
||||
if (state == .OutgoingInit) {
|
||||
// First state an outgoing call will go through
|
||||
} else if (state == .OutgoingProgress) {
|
||||
// Right after outgoing init
|
||||
} else if (state == .OutgoingRinging) {
|
||||
// This state will be reached upon reception of the 180 RINGING
|
||||
} else if (state == .Connected) {
|
||||
// When the 200 OK has been received
|
||||
} else if (state == .StreamsRunning) {
|
||||
// This state indicates the call is active.
|
||||
// You may reach this state multiple times, for example after a pause/resume
|
||||
// or after the ICE negotiation completes
|
||||
// Wait for the call to be connected before allowing a call update
|
||||
self.isCallRunning = true
|
||||
|
||||
// Only enable toggle camera button if there is more than 1 camera
|
||||
// We check if core.videoDevicesList.size > 2 because of the fake camera with static image created by our SDK (see below)
|
||||
self.canChangeCamera = core.videoDevicesList.count > 2
|
||||
} else if (state == .Paused) {
|
||||
// When you put a call in pause, it will became Paused
|
||||
self.canChangeCamera = false
|
||||
} else if (state == .PausedByRemote) {
|
||||
// When the remote end of the call pauses it, it will be PausedByRemote
|
||||
} else if (state == .Updating) {
|
||||
// When we request a call update, for example when toggling video
|
||||
} else if (state == .UpdatedByRemote) {
|
||||
// When the remote requests a call update
|
||||
} else if (state == .Released) {
|
||||
// Call state will be released shortly after the End state
|
||||
self.isCallRunning = false
|
||||
self.canChangeCamera = false
|
||||
} else if (state == .Error) {
|
||||
|
||||
}
|
||||
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
mCore.addDelegate(delegate: mCoreDelegate)
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
do {
|
||||
var transport : TransportType
|
||||
if (transportType == "TLS") { transport = TransportType.Tls }
|
||||
else if (transportType == "TCP") { transport = TransportType.Tcp }
|
||||
else { transport = TransportType.Udp }
|
||||
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
let accountParams = try mCore.createAccountParams()
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try! accountParams.setIdentityaddress(newValue: identity)
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
accountParams.registerEnabled = true
|
||||
mAccount = try mCore.createAccount(params: accountParams)
|
||||
mCore.addAuthInfo(info: authInfo)
|
||||
try mCore.addAccount(account: mAccount!)
|
||||
mCore.defaultAccount = mAccount
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func unregister()
|
||||
{
|
||||
if let account = mCore.defaultAccount {
|
||||
let params = account.params
|
||||
let clonedParams = params?.clone()
|
||||
clonedParams?.registerEnabled = false
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
if let account = mCore.defaultAccount {
|
||||
mCore.removeAccount(account: account)
|
||||
mCore.clearAccounts()
|
||||
mCore.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func outgoingCall() {
|
||||
do {
|
||||
// As for everything we need to get the SIP URI of the remote and convert it to an Address
|
||||
let remoteAddress = try Factory.Instance.createAddress(addr: remoteAddress)
|
||||
|
||||
// We also need a CallParams object
|
||||
// Create call params expects a Call object for incoming calls, but for outgoing we must use null safely
|
||||
let params = try mCore.createCallParams(call: nil)
|
||||
|
||||
// We can now configure it
|
||||
// Here we ask for no encryption but we could ask for ZRTP/SRTP/DTLS
|
||||
params.mediaEncryption = MediaEncryption.None
|
||||
// If we wanted to start the call with video directly
|
||||
//params.videoEnabled = true
|
||||
|
||||
// Finally we start the call
|
||||
let _ = mCore.inviteAddressWithParams(addr: remoteAddress, params: params)
|
||||
// Call process can be followed in onCallStateChanged callback from core listener
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
|
||||
}
|
||||
|
||||
func terminateCall() {
|
||||
do {
|
||||
if (mCore.callsNb == 0) { return }
|
||||
|
||||
// If the call state isn't paused, we can get it using core.currentCall
|
||||
let coreCall = (mCore.currentCall != nil) ? mCore.currentCall : mCore.calls[0]
|
||||
|
||||
// Terminating a call is quite simple
|
||||
if let call = coreCall {
|
||||
try call.terminate()
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func toggleVideo() {
|
||||
do {
|
||||
if (mCore.callsNb == 0) { return }
|
||||
let coreCall = (mCore.currentCall != nil) ? mCore.currentCall : mCore.calls[0]
|
||||
// We will need the CAMERA permission for video call
|
||||
|
||||
if let call = coreCall {
|
||||
// To update the call, we need to create a new call params, from the call object this time
|
||||
let params = try mCore.createCallParams(call: call)
|
||||
// Here we toggle the video state (disable it if enabled, enable it if disabled)
|
||||
// Note that we are using currentParams and not params or remoteParams
|
||||
// params is the object you configured when the call was started
|
||||
// remote params is the same but for the remote
|
||||
// current params is the real params of the call, resulting of the mix of local & remote params
|
||||
params.videoEnabled = !(call.currentParams!.videoEnabled)
|
||||
isVideoEnabled = params.videoEnabled
|
||||
// Finally we request the call update
|
||||
try call.update(params: params)
|
||||
// Note that when toggling off the video, TextureViews will keep showing the latest frame displayed
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func toggleCamera() {
|
||||
do {
|
||||
// Currently used camera
|
||||
let currentDevice = mCore.videoDevice
|
||||
|
||||
// Let's iterate over all camera available and choose another one
|
||||
for camera in mCore.videoDevicesList {
|
||||
// All devices will have a "Static picture" fake camera, and we don't want to use it
|
||||
if (camera != currentDevice && camera != "StaticImage: Static picture") {
|
||||
try mCore.setVideodevice(newValue: camera)
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func pauseOrResume() {
|
||||
do {
|
||||
if (mCore.callsNb == 0) { return }
|
||||
let coreCall = (mCore.currentCall != nil) ? mCore.currentCall : mCore.calls[0]
|
||||
|
||||
if let call = coreCall {
|
||||
if (call.state != Call.State.Paused && call.state != Call.State.Pausing) {
|
||||
// If our call isn't paused, let's pause it
|
||||
try call.pause()
|
||||
} else if (call.state != Call.State.Resuming) {
|
||||
// Otherwise let's resume it
|
||||
try call.resume()
|
||||
}
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
65
ios/swift/3-OutgoingCall/OutgoingCall/SceneDelegate.swift
Normal file
65
ios/swift/3-OutgoingCall/OutgoingCall/SceneDelegate.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// LoginTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
let delegate = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
24
ios/swift/3-OutgoingCall/Podfile
Normal file
24
ios/swift/3-OutgoingCall/Podfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
source "https://gitlab.linphone.org/BC/public/podspec.git"
|
||||
source "https://github.com/CocoaPods/Specs.git"
|
||||
|
||||
def basic_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '~> 5.0.0'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
target 'OutgoingCall' do
|
||||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for OutgoingCall
|
||||
basic_pods
|
||||
|
||||
end
|
8
ios/swift/3-OutgoingCall/README.md
Normal file
8
ios/swift/3-OutgoingCall/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
Outgoing call tutorial
|
||||
====================
|
||||
|
||||
In the previous tutorial we saw how to handle an incoming call, now let's start one.
|
||||
|
||||
We'll also see how to enable video during a call, switch between the front and back cameras if available and display our own preview.
|
||||
|
||||
Note that changes to the "info.plist" file were made to enable iphone cameras.
|
@ -0,0 +1,431 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
577005D03F6821591475FBF9 /* Pods_CallKitTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 454830E9C41DBBF20AF2BD05 /* Pods_CallKitTutorial.framework */; };
|
||||
6608A96624E197D5006E6C68 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A96524E197D5006E6C68 /* AppDelegate.swift */; };
|
||||
6608A96824E197D5006E6C68 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A96724E197D5006E6C68 /* SceneDelegate.swift */; };
|
||||
6608A96A24E197D5006E6C68 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A96924E197D5006E6C68 /* ContentView.swift */; };
|
||||
6608A96C24E197D5006E6C68 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6608A96B24E197D5006E6C68 /* Assets.xcassets */; };
|
||||
6608A96F24E197D5006E6C68 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6608A96E24E197D5006E6C68 /* Preview Assets.xcassets */; };
|
||||
6608A97224E197D5006E6C68 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */; };
|
||||
6608A97A24E19817006E6C68 /* CallKitTutorial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97924E19817006E6C68 /* CallKitTutorial.swift */; };
|
||||
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
018936DA8FE1500B9E181610 /* Pods-CallKitTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.debug.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
454830E9C41DBBF20AF2BD05 /* Pods_CallKitTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallKitTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6608A96224E197D5006E6C68 /* CallKitTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CallKitTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6608A96524E197D5006E6C68 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
6608A96724E197D5006E6C68 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
6608A96924E197D5006E6C68 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
6608A96B24E197D5006E6C68 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
6608A96E24E197D5006E6C68 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
6608A97124E197D5006E6C68 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
6608A97324E197D5006E6C68 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
6608A97924E19817006E6C68 /* CallKitTutorial.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitTutorial.swift; sourceTree = "<group>"; };
|
||||
6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitProviderDelegate.swift; sourceTree = "<group>"; };
|
||||
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CallKitTutorial.entitlements; sourceTree = "<group>"; };
|
||||
C87B170DFD4D3072825B25EF /* Pods-CallKitTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.release.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
6608A95F24E197D5006E6C68 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
577005D03F6821591475FBF9 /* Pods_CallKitTutorial.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
319770E3ECD19EBD7557F82B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
454830E9C41DBBF20AF2BD05 /* Pods_CallKitTutorial.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
38284A71627D413A7ACC2F07 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
018936DA8FE1500B9E181610 /* Pods-CallKitTutorial.debug.xcconfig */,
|
||||
C87B170DFD4D3072825B25EF /* Pods-CallKitTutorial.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6608A95924E197D5006E6C68 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6608A96424E197D5006E6C68 /* CallKitTutorial */,
|
||||
6608A96324E197D5006E6C68 /* Products */,
|
||||
38284A71627D413A7ACC2F07 /* Pods */,
|
||||
319770E3ECD19EBD7557F82B /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6608A96324E197D5006E6C68 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6608A96224E197D5006E6C68 /* CallKitTutorial.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6608A96424E197D5006E6C68 /* CallKitTutorial */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */,
|
||||
6608A96524E197D5006E6C68 /* AppDelegate.swift */,
|
||||
6608A96724E197D5006E6C68 /* SceneDelegate.swift */,
|
||||
6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */,
|
||||
6608A97924E19817006E6C68 /* CallKitTutorial.swift */,
|
||||
6608A96924E197D5006E6C68 /* ContentView.swift */,
|
||||
6608A96B24E197D5006E6C68 /* Assets.xcassets */,
|
||||
6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */,
|
||||
6608A97324E197D5006E6C68 /* Info.plist */,
|
||||
6608A96D24E197D5006E6C68 /* Preview Content */,
|
||||
);
|
||||
path = CallKitTutorial;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6608A96D24E197D5006E6C68 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6608A96E24E197D5006E6C68 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6608A96124E197D5006E6C68 /* CallKitTutorial */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6608A97624E197D5006E6C68 /* Build configuration list for PBXNativeTarget "CallKitTutorial" */;
|
||||
buildPhases = (
|
||||
D642DC4C3C74BB17FF5A3E9F /* [CP] Check Pods Manifest.lock */,
|
||||
6608A95E24E197D5006E6C68 /* Sources */,
|
||||
6608A95F24E197D5006E6C68 /* Frameworks */,
|
||||
6608A96024E197D5006E6C68 /* Resources */,
|
||||
640A5744B5ABBA6A3EDBFDB1 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = CallKitTutorial;
|
||||
productName = CallKitTutorial;
|
||||
productReference = 6608A96224E197D5006E6C68 /* CallKitTutorial.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
6608A95A24E197D5006E6C68 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1160;
|
||||
LastUpgradeCheck = 1160;
|
||||
ORGANIZATIONNAME = BelledonneCommunications;
|
||||
TargetAttributes = {
|
||||
6608A96124E197D5006E6C68 = {
|
||||
CreatedOnToolsVersion = 11.6;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 6608A95D24E197D5006E6C68 /* Build configuration list for PBXProject "CallKitTutorial" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 6608A95924E197D5006E6C68;
|
||||
productRefGroup = 6608A96324E197D5006E6C68 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
6608A96124E197D5006E6C68 /* CallKitTutorial */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
6608A96024E197D5006E6C68 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6608A97224E197D5006E6C68 /* LaunchScreen.storyboard in Resources */,
|
||||
6608A96F24E197D5006E6C68 /* Preview Assets.xcassets in Resources */,
|
||||
6608A96C24E197D5006E6C68 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
640A5744B5ABBA6A3EDBFDB1 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D642DC4C3C74BB17FF5A3E9F /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-CallKitTutorial-checkManifestLockResult.txt",
|
||||
);
|
||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
6608A95E24E197D5006E6C68 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6608A97A24E19817006E6C68 /* CallKitTutorial.swift in Sources */,
|
||||
6608A96624E197D5006E6C68 /* AppDelegate.swift in Sources */,
|
||||
6608A96824E197D5006E6C68 /* SceneDelegate.swift in Sources */,
|
||||
6608A96A24E197D5006E6C68 /* ContentView.swift in Sources */,
|
||||
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
6608A97124E197D5006E6C68 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
6608A97424E197D5006E6C68 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 13.6;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6608A97524E197D5006E6C68 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 13.6;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6608A97724E197D5006E6C68 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 018936DA8FE1500B9E181610 /* Pods-CallKitTutorial.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = CallKitTutorial/CallKitTutorial.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"CallKitTutorial/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = CallKitTutorial/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.callkit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6608A97824E197D5006E6C68 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C87B170DFD4D3072825B25EF /* Pods-CallKitTutorial.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = CallKitTutorial/CallKitTutorial.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"CallKitTutorial/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = CallKitTutorial/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.callkit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
6608A95D24E197D5006E6C68 /* Build configuration list for PBXProject "CallKitTutorial" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6608A97424E197D5006E6C68 /* Debug */,
|
||||
6608A97524E197D5006E6C68 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6608A97624E197D5006E6C68 /* Build configuration list for PBXNativeTarget "CallKitTutorial" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6608A97724E197D5006E6C68 /* Debug */,
|
||||
6608A97824E197D5006E6C68 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 6608A95A24E197D5006E6C68 /* Project object */;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:CallKitTutorial.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,8 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// CallKitTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 10/08/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@ObservedObject var tutorialContext = CallKitExampleContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
@ -0,0 +1,99 @@
|
||||
//
|
||||
// ProviderDelegate.swift
|
||||
// CallTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 05/08/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CallKit
|
||||
import linphonesw
|
||||
import AVFoundation
|
||||
|
||||
|
||||
class CallKitProviderDelegate : NSObject
|
||||
{
|
||||
private let provider: CXProvider
|
||||
let mCallController = CXCallController()
|
||||
var tutorialContext : CallKitExampleContext!
|
||||
|
||||
var incomingCallUUID : UUID!
|
||||
|
||||
init(context: CallKitExampleContext)
|
||||
{
|
||||
tutorialContext = context
|
||||
let providerConfiguration = CXProviderConfiguration(localizedName: Bundle.main.infoDictionary!["CFBundleName"] as! String)
|
||||
providerConfiguration.supportsVideo = true
|
||||
providerConfiguration.supportedHandleTypes = [.generic]
|
||||
|
||||
providerConfiguration.maximumCallsPerCallGroup = 1
|
||||
providerConfiguration.maximumCallGroups = 1
|
||||
|
||||
provider = CXProvider(configuration: providerConfiguration)
|
||||
super.init()
|
||||
provider.setDelegate(self, queue: nil) // The CXProvider delegate will trigger CallKit related callbacks
|
||||
|
||||
}
|
||||
|
||||
func incomingCall()
|
||||
{
|
||||
incomingCallUUID = UUID()
|
||||
let update = CXCallUpdate()
|
||||
update.remoteHandle = CXHandle(type:.generic, value: tutorialContext.incomingCallName)
|
||||
|
||||
provider.reportNewIncomingCall(with: incomingCallUUID, update: update, completion: { error in }) // Report to CallKit a call is incoming
|
||||
}
|
||||
|
||||
func stopCall()
|
||||
{
|
||||
let endCallAction = CXEndCallAction(call: incomingCallUUID)
|
||||
let transaction = CXTransaction(action: endCallAction)
|
||||
|
||||
mCallController.request(transaction, completion: { error in }) // Report to CallKit a call must end
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// In this extension, we implement the action we want to be done when CallKit is notified of something.
|
||||
// This can happen through the CallKit GUI in the app, or directly in the code (see, incomingCall(), stopCall() functions above)
|
||||
extension CallKitProviderDelegate: CXProviderDelegate {
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
||||
do {
|
||||
if (tutorialContext.mCall?.state != .End && tutorialContext.mCall?.state != .Released) {
|
||||
try tutorialContext.mCall?.terminate()
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
|
||||
tutorialContext.isCallRunning = false
|
||||
tutorialContext.isCallIncoming = false
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
||||
do {
|
||||
try tutorialContext.mCall?.accept()
|
||||
tutorialContext.isCallRunning = true
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {}
|
||||
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {}
|
||||
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {}
|
||||
func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) {}
|
||||
func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {}
|
||||
func providerDidReset(_ provider: CXProvider) {}
|
||||
|
||||
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
|
||||
tutorialContext.mCore.activateAudioSession(actived: true)
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
||||
tutorialContext.mCore.activateAudioSession(actived: false)
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?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>aps-environment</key>
|
||||
<string>development</string>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,141 @@
|
||||
//
|
||||
// CallExample.swift
|
||||
// CallTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import linphonesw
|
||||
import AVFoundation
|
||||
|
||||
class CallKitExampleContext : ObservableObject
|
||||
{
|
||||
var mCore: Core!
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
|
||||
var mAccount: Account?
|
||||
var mCoreDelegate : CoreDelegate!
|
||||
@Published var username : String = "quentindev"
|
||||
@Published var passwd : String = "dev"
|
||||
@Published var domain : String = "sip.linphone.org"
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var transportType : String = "TLS"
|
||||
|
||||
@Published var callMsg : String = ""
|
||||
@Published var isCallIncoming : Bool = false
|
||||
@Published var isCallRunning : Bool = false
|
||||
@Published var remoteAddress : String = "Nobody yet"
|
||||
@Published var isSpeakerEnabled : Bool = false
|
||||
@Published var isMicrophoneEnabled : Bool = false
|
||||
|
||||
/*------------ Callkit tutorial related variables ---------------*/
|
||||
let incomingCallName = "Incoming call example"
|
||||
var mCall : Call?
|
||||
var mProviderDelegate : CallKitProviderDelegate!
|
||||
var mCallAlreadyStopped : Bool = false;
|
||||
|
||||
init()
|
||||
{
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
let factory = Factory.Instance
|
||||
// IMPORTANT : In this tutorial, we require the use of a core configuration file.
|
||||
// This way, once the registration is done, and until it is cleared, it will return to the LoggedIn state on launch.
|
||||
// This allows us to have a functional call when the app was closed and is started by a VOIP push notification (incoming call
|
||||
// We also need to enable "Push Notitifications" and "Background Mode - Voice Over IP"
|
||||
let configDir = factory.getConfigDir(context: nil)
|
||||
try? mCore = factory.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
|
||||
mProviderDelegate = CallKitProviderDelegate(context: self)
|
||||
// enabling push notifications management in the core
|
||||
mCore.callkitEnabled = true
|
||||
mCore.pushNotificationEnabled = true
|
||||
try? mCore.start()
|
||||
|
||||
mCoreDelegate = CoreDelegateStub( onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||
self.callMsg = message
|
||||
|
||||
if (state == .PushIncomingReceived){
|
||||
// We're being called by someone (and app is in background)
|
||||
self.mCall = call
|
||||
self.isCallIncoming = true
|
||||
self.mProviderDelegate.incomingCall()
|
||||
} else if (state == .IncomingReceived) {
|
||||
// If app is in foreground, it's likely that we will receive the SIP invite before the Push notification
|
||||
if (!self.isCallIncoming) {
|
||||
self.mCall = call
|
||||
self.isCallIncoming = true
|
||||
self.mProviderDelegate.incomingCall()
|
||||
}
|
||||
self.remoteAddress = call.remoteAddress!.asStringUriOnly()
|
||||
} else if (state == .Connected) {
|
||||
self.isCallIncoming = false
|
||||
self.isCallRunning = true
|
||||
} else if (state == .Released || state == .End || state == .Error) {
|
||||
// Call has been terminated by any side
|
||||
|
||||
// Report to CallKit that the call is over, if the terminate action was initiated by other end of the call
|
||||
if (self.isCallRunning) {
|
||||
self.mProviderDelegate.stopCall()
|
||||
}
|
||||
self.remoteAddress = "Nobody yet"
|
||||
}
|
||||
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
// Since core has "Push Enabled", the reception and setting of the push notification token is done automatically
|
||||
// It should have been set and used when we log in, you can check here or in the liblinphone logs
|
||||
NSLog("Account registered Push voip token: \(account.params?.pushNotificationConfig?.voipToken)")
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
mCore.addDelegate(delegate: mCoreDelegate)
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
do {
|
||||
var transport : TransportType
|
||||
if (transportType == "TLS") { transport = TransportType.Tls }
|
||||
else if (transportType == "TCP") { transport = TransportType.Tcp }
|
||||
else { transport = TransportType.Udp }
|
||||
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
let accountParams = try mCore.createAccountParams()
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try! accountParams.setIdentityaddress(newValue: identity)
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
accountParams.registerEnabled = true
|
||||
// Enable push notifications on this account
|
||||
accountParams.pushNotificationAllowed = true
|
||||
// We're in a sandbox application, so we must set the provider to "apns.dev" since it will be "apns" by default, which is used only for production apps
|
||||
accountParams.pushNotificationConfig?.provider = "apns.dev"
|
||||
mAccount = try mCore.createAccount(params: accountParams)
|
||||
mCore.addAuthInfo(info: authInfo)
|
||||
try mCore.addAccount(account: mAccount!)
|
||||
mCore.defaultAccount = mAccount
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func unregister()
|
||||
{
|
||||
if let account = mCore.defaultAccount {
|
||||
let params = account.params
|
||||
let clonedParams = params?.clone()
|
||||
clonedParams?.registerEnabled = false
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
if let account = mCore.defaultAccount {
|
||||
mCore.removeAccount(account: account)
|
||||
mCore.clearAccounts()
|
||||
mCore.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
}
|
116
ios/swift/4-CallKitTutorial/CallKitTutorial/ContentView.swift
Normal file
116
ios/swift/4-CallKitTutorial/CallKitTutorial/ContentView.swift
Normal file
@ -0,0 +1,116 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// CallKit tutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 09/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : CallKitExampleContext
|
||||
|
||||
func callStateString() -> String {
|
||||
if (tutorialContext.isCallRunning) {
|
||||
return "Call running"
|
||||
} else if (tutorialContext.isCallIncoming) {
|
||||
return "Incoming call"
|
||||
} else {
|
||||
return "No Call"
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
HStack {
|
||||
Text("Username:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.username)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Password:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.passwd)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Domain:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.domain)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
Picker(selection: $tutorialContext.transportType, label: Text("Transport:")) {
|
||||
Text("TLS").tag("TLS")
|
||||
Text("TCP").tag("TCP")
|
||||
Text("UDP").tag("UDP")
|
||||
}.pickerStyle(SegmentedPickerStyle()).padding()
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.loggedIn)
|
||||
{
|
||||
self.tutorialContext.unregister()
|
||||
self.tutorialContext.delete()
|
||||
} else {
|
||||
self.tutorialContext.login()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text(tutorialContext.loggedIn ? "Log out & \ndelete account" : "Create & \nlog in account")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 220.0, height: 90)
|
||||
.background(Color.gray)
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Text("Login State : ")
|
||||
.font(.footnote)
|
||||
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
|
||||
.font(.footnote)
|
||||
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
|
||||
}.padding(.top, 10.0)
|
||||
}
|
||||
VStack {
|
||||
HStack {
|
||||
Text("Caller:").font(.title).underline()
|
||||
Text(tutorialContext.remoteAddress)
|
||||
Spacer()
|
||||
}.padding(.top, 5)
|
||||
HStack {
|
||||
Text("Call msg:").font(.title3).underline()
|
||||
Text(tutorialContext.callMsg)
|
||||
Spacer()
|
||||
}.padding(.top, 5)
|
||||
}.padding(.top, 30)
|
||||
Button(action: tutorialContext.mProviderDelegate.stopCall)
|
||||
{
|
||||
Text("End call").font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 120.0, height: 42.0)
|
||||
.background(Color.gray)
|
||||
}.disabled(!tutorialContext.isCallRunning)
|
||||
.padding(.top, 10)
|
||||
}
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Core Version is \(tutorialContext.coreVersion)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: CallKitExampleContext())
|
||||
}
|
||||
}
|
70
ios/swift/4-CallKitTutorial/CallKitTutorial/Info.plist
Normal file
70
ios/swift/4-CallKitTutorial/CallKitTutorial/Info.plist
Normal file
@ -0,0 +1,70 @@
|
||||
<?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>$(DEVELOPMENT_LANGUAGE)</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>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string></string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Camera access</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Microphone access</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// CallKitTutorial
|
||||
//
|
||||
// Created by QuentinArguillere on 10/08/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let delegate = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
source "https://gitlab.linphone.org/BC/public/podspec.git"
|
||||
#source "https://github.com/CocoaPods/Specs.git"
|
||||
source "https://github.com/CocoaPods/Specs.git"
|
||||
|
||||
def basic_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '~> 4.4.0'
|
||||
pod 'linphone-sdk', '~> 5.0.0'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
@ -14,11 +14,11 @@ end
|
||||
|
||||
|
||||
|
||||
target 'HelloLinphone' do
|
||||
target 'CallKitTutorial' do
|
||||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for HelloLinphone
|
||||
# Pods for CallKitTutorial
|
||||
basic_pods
|
||||
|
||||
end
|
10
ios/swift/4-CallKitTutorial/README.md
Normal file
10
ios/swift/4-CallKitTutorial/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
Push notifications tutorial
|
||||
====================
|
||||
|
||||
On mobile devices (Android & iOS), you probably want your app to be reachable even if it's not in the foreground.
|
||||
|
||||
To do that you need it to be able to receive push notifications from your SIP proxy, and in this tutorial, using [Apple Push Notification Service](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html), you'll learn how to simply send the device push information to your server.
|
||||
|
||||
Apple will also require you to use their CallKit API when you receive a push notification, you must always notify CallKit when you receive a VOIP Push or your app will be terminated. If you use the "Core.pushEnabled=true" settings, as is done in this app, most of this work is done in the sdk and you only require to notify an incoming call when your Core Delegate notifies you of a new call.
|
||||
|
||||
Compared to the previous tutorials, some changes have been required in `CallKitTutorial.xcodeproj` in order to enable `Push Notifications` and `BackGround Modes (Voice Over IP)` in the capabilities of your project.
|
424
ios/swift/5-BasicChat/BasicChat.xcodeproj/project.pbxproj
Normal file
424
ios/swift/5-BasicChat/BasicChat.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,424 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
34397F2DCE0A26771A291122 /* Pods_BasicChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BDC97FF3DCFB7B82244F46 /* Pods_BasicChat.framework */; };
|
||||
664BC0E326EF459B007EE298 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0E226EF459B007EE298 /* AppDelegate.swift */; };
|
||||
664BC0E526EF459B007EE298 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0E426EF459B007EE298 /* SceneDelegate.swift */; };
|
||||
664BC0E726EF459B007EE298 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0E626EF459B007EE298 /* ContentView.swift */; };
|
||||
664BC0E926EF459D007EE298 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664BC0E826EF459D007EE298 /* Assets.xcassets */; };
|
||||
664BC0EC26EF459D007EE298 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664BC0EB26EF459D007EE298 /* Preview Assets.xcassets */; };
|
||||
664BC0EF26EF459D007EE298 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 664BC0ED26EF459D007EE298 /* LaunchScreen.storyboard */; };
|
||||
664BC0F726EF481A007EE298 /* BasicChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC0F626EF481A007EE298 /* BasicChat.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
17BDC97FF3DCFB7B82244F46 /* Pods_BasicChat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BasicChat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
664BC0DF26EF459B007EE298 /* BasicChat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BasicChat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
664BC0E226EF459B007EE298 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
664BC0E426EF459B007EE298 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
664BC0E626EF459B007EE298 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
664BC0E826EF459D007EE298 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
664BC0EB26EF459D007EE298 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
664BC0EE26EF459D007EE298 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
664BC0F026EF459D007EE298 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
664BC0F626EF481A007EE298 /* BasicChat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicChat.swift; sourceTree = "<group>"; };
|
||||
C9B5BB74C5F76BED02B82031 /* Pods-BasicChat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BasicChat.release.xcconfig"; path = "Target Support Files/Pods-BasicChat/Pods-BasicChat.release.xcconfig"; sourceTree = "<group>"; };
|
||||
F46732417EF2391C68D697D6 /* Pods-BasicChat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BasicChat.debug.xcconfig"; path = "Target Support Files/Pods-BasicChat/Pods-BasicChat.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
664BC0DC26EF459B007EE298 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
34397F2DCE0A26771A291122 /* Pods_BasicChat.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
05AF3043CF55B85A1A53217A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
17BDC97FF3DCFB7B82244F46 /* Pods_BasicChat.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0D626EF459B007EE298 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0E126EF459B007EE298 /* BasicChat */,
|
||||
664BC0E026EF459B007EE298 /* Products */,
|
||||
9DDE73864BE97E2EE2764318 /* Pods */,
|
||||
05AF3043CF55B85A1A53217A /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0E026EF459B007EE298 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0DF26EF459B007EE298 /* BasicChat.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0E126EF459B007EE298 /* BasicChat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0E226EF459B007EE298 /* AppDelegate.swift */,
|
||||
664BC0E426EF459B007EE298 /* SceneDelegate.swift */,
|
||||
664BC0E626EF459B007EE298 /* ContentView.swift */,
|
||||
664BC0E826EF459D007EE298 /* Assets.xcassets */,
|
||||
664BC0ED26EF459D007EE298 /* LaunchScreen.storyboard */,
|
||||
664BC0F026EF459D007EE298 /* Info.plist */,
|
||||
664BC0F626EF481A007EE298 /* BasicChat.swift */,
|
||||
664BC0EA26EF459D007EE298 /* Preview Content */,
|
||||
);
|
||||
path = BasicChat;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC0EA26EF459D007EE298 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC0EB26EF459D007EE298 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9DDE73864BE97E2EE2764318 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F46732417EF2391C68D697D6 /* Pods-BasicChat.debug.xcconfig */,
|
||||
C9B5BB74C5F76BED02B82031 /* Pods-BasicChat.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
664BC0DE26EF459B007EE298 /* BasicChat */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 664BC0F326EF459D007EE298 /* Build configuration list for PBXNativeTarget "BasicChat" */;
|
||||
buildPhases = (
|
||||
24E9CA4BD04B47A0932B80AF /* [CP] Check Pods Manifest.lock */,
|
||||
664BC0DB26EF459B007EE298 /* Sources */,
|
||||
664BC0DC26EF459B007EE298 /* Frameworks */,
|
||||
664BC0DD26EF459B007EE298 /* Resources */,
|
||||
3288DCA5B7DA5A1E061B4A8E /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = BasicChat;
|
||||
productName = BasicChat;
|
||||
productReference = 664BC0DF26EF459B007EE298 /* BasicChat.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
664BC0D726EF459B007EE298 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1250;
|
||||
LastUpgradeCheck = 1250;
|
||||
TargetAttributes = {
|
||||
664BC0DE26EF459B007EE298 = {
|
||||
CreatedOnToolsVersion = 12.5.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 664BC0DA26EF459B007EE298 /* Build configuration list for PBXProject "BasicChat" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 664BC0D626EF459B007EE298;
|
||||
productRefGroup = 664BC0E026EF459B007EE298 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
664BC0DE26EF459B007EE298 /* BasicChat */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
664BC0DD26EF459B007EE298 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
664BC0EF26EF459D007EE298 /* LaunchScreen.storyboard in Resources */,
|
||||
664BC0EC26EF459D007EE298 /* Preview Assets.xcassets in Resources */,
|
||||
664BC0E926EF459D007EE298 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
24E9CA4BD04B47A0932B80AF /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-BasicChat-checkManifestLockResult.txt",
|
||||
);
|
||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3288DCA5B7DA5A1E061B4A8E /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-BasicChat/Pods-BasicChat-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-BasicChat/Pods-BasicChat-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BasicChat/Pods-BasicChat-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
664BC0DB26EF459B007EE298 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
664BC0F726EF481A007EE298 /* BasicChat.swift in Sources */,
|
||||
664BC0E326EF459B007EE298 /* AppDelegate.swift in Sources */,
|
||||
664BC0E526EF459B007EE298 /* SceneDelegate.swift in Sources */,
|
||||
664BC0E726EF459B007EE298 /* ContentView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
664BC0ED26EF459D007EE298 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
664BC0EE26EF459D007EE298 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
664BC0F126EF459D007EE298 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
664BC0F226EF459D007EE298 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
664BC0F426EF459D007EE298 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F46732417EF2391C68D697D6 /* Pods-BasicChat.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"BasicChat/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = BasicChat/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.BasicChat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
664BC0F526EF459D007EE298 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C9B5BB74C5F76BED02B82031 /* Pods-BasicChat.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"BasicChat/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = BasicChat/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.BasicChat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
664BC0DA26EF459B007EE298 /* Build configuration list for PBXProject "BasicChat" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
664BC0F126EF459D007EE298 /* Debug */,
|
||||
664BC0F226EF459D007EE298 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
664BC0F326EF459D007EE298 /* Build configuration list for PBXNativeTarget "BasicChat" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
664BC0F426EF459D007EE298 /* Debug */,
|
||||
664BC0F526EF459D007EE298 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 664BC0D726EF459B007EE298 /* Project object */;
|
||||
}
|
7
ios/swift/5-BasicChat/BasicChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/swift/5-BasicChat/BasicChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,8 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
38
ios/swift/5-BasicChat/BasicChat/AppDelegate.swift
Normal file
38
ios/swift/5-BasicChat/BasicChat/AppDelegate.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// BasicChat
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@ObservedObject var tutorialContext = BasicChatTutorialContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
241
ios/swift/5-BasicChat/BasicChat/BasicChat.swift
Normal file
241
ios/swift/5-BasicChat/BasicChat/BasicChat.swift
Normal file
@ -0,0 +1,241 @@
|
||||
//
|
||||
// BasicChat.swift
|
||||
// BasicChat
|
||||
//
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import linphonesw
|
||||
|
||||
|
||||
|
||||
class BasicChatTutorialContext : ObservableObject
|
||||
{
|
||||
var mCore: Core!
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
|
||||
var mRegistrationDelegate : CoreDelegate!
|
||||
@Published var username : String = "user"
|
||||
@Published var passwd : String = "pwd"
|
||||
@Published var domain : String = "sip.example.org"
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var transportType : String = "TLS"
|
||||
|
||||
/*------------ Basic chat tutorial related variables -------*/
|
||||
var mChatroom : ChatRoom?
|
||||
var mChatMessageDelegate : ChatMessageDelegate!
|
||||
var mChatMessage : ChatMessage?
|
||||
var mLastFileMessageReceived : ChatMessage?
|
||||
@Published var msgToSend : String = "msg"
|
||||
@Published var remoteAddress : String = "sip:remote@sip.example.org"
|
||||
@Published var canEditAddress : Bool = true
|
||||
@Published var isDownloading : Bool = false
|
||||
@Published var messagesReceived : String = ""
|
||||
var fileFolderUrl : URL!
|
||||
var fileUrl : URL!
|
||||
|
||||
init()
|
||||
{
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
|
||||
try? mCore.start()
|
||||
|
||||
mRegistrationDelegate = CoreDelegateStub(onMessageReceived : { (core: Core, chatRoom: ChatRoom, message: ChatMessage) in
|
||||
// We will be called in this when a message is received
|
||||
// If the chat room wasn't existing, it is automatically created by the library
|
||||
// If we already sent a chat message, the chatRoom variable will be the same as the one we already have
|
||||
if (self.mChatroom == nil) {
|
||||
if (chatRoom.hasCapability(mask: ChatRoomCapabilities.Basic.rawValue)) {
|
||||
// Keep the chatRoom object to use it to send messages if it hasn't been created yet
|
||||
self.mChatroom = chatRoom
|
||||
if let remoteAddress = chatRoom.peerAddress?.asStringUriOnly() {
|
||||
self.remoteAddress = remoteAddress
|
||||
}
|
||||
self.canEditAddress = false
|
||||
}
|
||||
}
|
||||
// We will notify the sender the message has been read by us
|
||||
chatRoom.markAsRead()
|
||||
|
||||
for content in message.contents {
|
||||
if (content.isFileTransfer) {
|
||||
self.mLastFileMessageReceived = message
|
||||
self.messagesReceived += "\n--File available for download--"
|
||||
} else if (content.isText) {
|
||||
self.messagesReceived += "\nThem: \(message.utf8Text)"
|
||||
}
|
||||
}
|
||||
|
||||
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
mCore.addDelegate(delegate: mRegistrationDelegate)
|
||||
|
||||
// This delegate has to be attached to each specific chat message we want to monitor, before sending it
|
||||
mChatMessageDelegate = ChatMessageDelegateStub(onMsgStateChanged : { (message: ChatMessage, state: ChatMessage.State) in
|
||||
print("MessageTrace - msg state changed: \(state)\n")
|
||||
if (state == ChatMessage.State.FileTransferDone && self.isDownloading == true) {
|
||||
self.isDownloading = false
|
||||
} else if (state == .Delivered) {
|
||||
self.messagesReceived += "\nMe: \(message.utf8Text)"
|
||||
}
|
||||
})
|
||||
|
||||
// example file to send
|
||||
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
|
||||
fileFolderUrl = documentsPath.appendingPathComponent("TutorialFiles")
|
||||
fileUrl = fileFolderUrl?.appendingPathComponent("file_to_transfer.txt")
|
||||
do{
|
||||
try FileManager.default.createDirectory(atPath: fileFolderUrl!.path, withIntermediateDirectories: true, attributes: nil)
|
||||
try String("My file content").write(to: fileUrl!, atomically: false, encoding: .utf8)
|
||||
}catch let error as NSError{
|
||||
print("Unable to create d)irectory",error)
|
||||
}
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
do {
|
||||
var transport : TransportType
|
||||
if (transportType == "TLS") { transport = TransportType.Tls }
|
||||
else if (transportType == "TCP") { transport = TransportType.Tcp }
|
||||
else { transport = TransportType.Udp }
|
||||
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
let accountParams = try mCore.createAccountParams()
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try! accountParams.setIdentityaddress(newValue: identity)
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
accountParams.registerEnabled = true
|
||||
let account = try mCore.createAccount(params: accountParams)
|
||||
|
||||
mCore.addAuthInfo(info: authInfo)
|
||||
try mCore.addAccount(account: account)
|
||||
|
||||
mCore.defaultAccount = account
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func unregister()
|
||||
{
|
||||
if let account = mCore.defaultAccount {
|
||||
let params = account.params
|
||||
let clonedParams = params?.clone()
|
||||
clonedParams?.registerEnabled = false
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
if let account = mCore.defaultAccount {
|
||||
mCore.removeAccount(account: account)
|
||||
mCore.clearAccounts()
|
||||
mCore.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
|
||||
func createBasicChatRoom() {
|
||||
do {
|
||||
// In this tutorial we will create a Basic chat room
|
||||
// It doesn't include advanced features such as end-to-end encryption or groups
|
||||
// But it is interoperable with any SIP service as it's relying on SIP SIMPLE messages
|
||||
// If you try to enable a feature not supported by the basic backend, isValid() will return false
|
||||
let params = try mCore.createDefaultChatRoomParams()
|
||||
params.backend = ChatRoomBackend.Basic
|
||||
params.encryptionEnabled = false
|
||||
params.groupEnabled = false
|
||||
|
||||
if (params.isValid) {
|
||||
// We also need the SIP address of the person we will chat with
|
||||
let remote = try Factory.Instance.createAddress(addr: remoteAddress)
|
||||
// And finally we will need our local SIP address
|
||||
let localAddress = mCore.defaultAccount?.params?.identityAddress
|
||||
mChatroom = try mCore.createChatRoom(params: params, localAddr: localAddress, participants: [remote])
|
||||
if (mChatroom != nil) {
|
||||
canEditAddress = false
|
||||
}
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func sendMessage() {
|
||||
do {
|
||||
if (mChatroom == nil) {
|
||||
// We need a ChatRoom object to send chat messages in it, so let's create it if it hasn't been done yet
|
||||
createBasicChatRoom()
|
||||
}
|
||||
mChatMessage = nil
|
||||
// We need to create a ChatMessage object using the ChatRoom
|
||||
mChatMessage = try mChatroom!.createMessageFromUtf8(message: msgToSend)
|
||||
|
||||
// Then we can send it, progress will be notified using the onMsgStateChanged callback
|
||||
mChatMessage!.addDelegate(delegate: mChatMessageDelegate)
|
||||
|
||||
// Send the message
|
||||
mChatMessage!.send()
|
||||
|
||||
// Clear the message input field
|
||||
msgToSend.removeAll()
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func sendFile() {
|
||||
do {
|
||||
if (mChatroom == nil) {
|
||||
// We need a ChatRoom object to send chat messages in it, so let's create it if it hasn't been done yet
|
||||
createBasicChatRoom()
|
||||
}
|
||||
|
||||
// We need to create a Content for our file transfer
|
||||
let content = try Factory.Instance.createContent()
|
||||
// Every content needs a content type & subtype
|
||||
content.name = "file_to_transfer.txt"
|
||||
content.type = "text"
|
||||
content.subtype = "plain"
|
||||
|
||||
// The simplest way to upload a file is to provide it's path
|
||||
content.filePath = fileUrl.path
|
||||
|
||||
// We need to create a ChatMessage object using the ChatRoom
|
||||
let chatMessage = try mChatroom!.createFileTransferMessage(initialContent: content)
|
||||
|
||||
// Then we can send it, progress will be notified using the onMsgStateChanged callback
|
||||
chatMessage.addDelegate(delegate: mChatMessageDelegate)
|
||||
|
||||
// Ensure a file sharing server URL is correctly set in the Core
|
||||
mCore.fileTransferServer = "https://www.linphone.org:444/lft.php"
|
||||
|
||||
// Send the message
|
||||
chatMessage.send()
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
|
||||
func downloadLastFileMessage() {
|
||||
if let message = mLastFileMessageReceived {
|
||||
for content in message.contents {
|
||||
if (content.isFileTransfer && content.filePath.isEmpty) {
|
||||
let contentName = content.name
|
||||
if (!contentName.isEmpty) {
|
||||
content.filePath = fileFolderUrl!.appendingPathComponent(contentName).path
|
||||
print("Start downloading \(content.name) into \(content.filePath)")
|
||||
isDownloading = true
|
||||
if (!message.downloadContent(content: content)) {
|
||||
print ("Download of \(contentName) failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
144
ios/swift/5-BasicChat/BasicChat/ContentView.swift
Normal file
144
ios/swift/5-BasicChat/BasicChat/ContentView.swift
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// BasicChat
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ActivityIndicator: UIViewRepresentable {
|
||||
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView
|
||||
{
|
||||
return UIActivityIndicatorView(style: .medium)
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>)
|
||||
{
|
||||
uiView.startAnimating()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : BasicChatTutorialContext
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
HStack {
|
||||
Text("Username:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.username)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Password:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.passwd)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Domain:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.domain)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
Picker(selection: $tutorialContext.transportType, label: Text("Transport:")) {
|
||||
Text("TLS").tag("TLS")
|
||||
Text("TCP").tag("TCP")
|
||||
Text("UDP").tag("UDP")
|
||||
}.pickerStyle(SegmentedPickerStyle()).padding()
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.loggedIn)
|
||||
{
|
||||
self.tutorialContext.unregister()
|
||||
self.tutorialContext.delete()
|
||||
} else {
|
||||
self.tutorialContext.login()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text(tutorialContext.loggedIn ? "Log out & \ndelete account" : "Create & \nlog in account")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 220.0, height: 90)
|
||||
.background(Color.gray)
|
||||
}
|
||||
|
||||
}
|
||||
HStack {
|
||||
Text("Login State : ")
|
||||
.font(.footnote)
|
||||
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
|
||||
.font(.footnote)
|
||||
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
|
||||
}.padding(.top, 10.0)
|
||||
HStack {
|
||||
Text("Chat with:")
|
||||
TextField("", text : $tutorialContext.remoteAddress)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(!tutorialContext.canEditAddress)
|
||||
}
|
||||
Text("Chat received").bold()
|
||||
ScrollView {
|
||||
Text(tutorialContext.messagesReceived)
|
||||
.font(.footnote)
|
||||
.frame(width: 330, height: 400)
|
||||
}.border(Color.gray)
|
||||
HStack {
|
||||
TextField("Sent text", text : $tutorialContext.msgToSend)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
Button(action: tutorialContext.sendMessage)
|
||||
{
|
||||
Text("Send")
|
||||
.font(.callout)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 50.0, height: 30.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Button(action: tutorialContext.sendFile)
|
||||
{
|
||||
Text("Send example \n file")
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(width: 120.0, height: 50.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
Button(action: tutorialContext.downloadLastFileMessage)
|
||||
{
|
||||
Text("Download last files \n received")
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(width: 150.0, height: 50.0)
|
||||
.background(Color.gray)
|
||||
}.disabled(tutorialContext.mLastFileMessageReceived == nil)
|
||||
if (tutorialContext.isDownloading) {
|
||||
ActivityIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Core Version is \(tutorialContext.coreVersion)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: BasicChatTutorialContext())
|
||||
}
|
||||
}
|
62
ios/swift/5-BasicChat/BasicChat/Info.plist
Normal file
62
ios/swift/5-BasicChat/BasicChat/Info.plist
Normal file
@ -0,0 +1,62 @@
|
||||
<?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>$(DEVELOPMENT_LANGUAGE)</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>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
65
ios/swift/5-BasicChat/BasicChat/SceneDelegate.swift
Normal file
65
ios/swift/5-BasicChat/BasicChat/SceneDelegate.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// BasicChat
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
|
||||
let delegate = UIApplication.shared.delegate as! AppDelegate
|
||||
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
|
||||
|
||||
// Use a UIHostingController as window root view controller.
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = UIHostingController(rootView: contentView)
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
24
ios/swift/5-BasicChat/Podfile
Normal file
24
ios/swift/5-BasicChat/Podfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
source "https://gitlab.linphone.org/BC/public/podspec.git"
|
||||
source "https://github.com/CocoaPods/Specs.git"
|
||||
|
||||
def basic_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '~> 5.0.0'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
target 'BasicChat' do
|
||||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for BasicChat
|
||||
basic_pods
|
||||
|
||||
end
|
8
ios/swift/5-BasicChat/README.md
Normal file
8
ios/swift/5-BasicChat/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
Basic chat tutorial
|
||||
====================
|
||||
|
||||
This tutorial will demonstrate how to send and display a simple SIP message containing either text or an image (but it works the same for any kind of file).
|
||||
|
||||
Note that for file transfer, a file transfer server is required. In this tutorial we'll use the one at `https://www.linphone.org:444/lft.php` that we use in our own linphone-android and linphone-iphone apps, but you can get its [source code](https://gitlab.linphone.org/BC/public/flexisip-http-file-transfer-server) and deploy your own.
|
||||
|
||||
Messages sent in this tutorial are standard SIP messages, so no matter the SIP proxy server you are using it should work, unlike the next [advanced chat tutorial](https://gitlab.linphone.org/BC/public/tutorials/-/tree/master/ios/swift/6-AdvancedChat).
|
424
ios/swift/6-AdvancedChat/AdvancedChat.xcodeproj/project.pbxproj
Normal file
424
ios/swift/6-AdvancedChat/AdvancedChat.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,424 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
5F916A81CD75D10483A4DAC8 /* Pods_AdvancedChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E72FBDC953F141F267B03540 /* Pods_AdvancedChat.framework */; };
|
||||
664BC12726F0CA1F007EE298 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC12626F0CA1F007EE298 /* AppDelegate.swift */; };
|
||||
664BC12926F0CA1F007EE298 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC12826F0CA1F007EE298 /* SceneDelegate.swift */; };
|
||||
664BC12B26F0CA1F007EE298 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC12A26F0CA1F007EE298 /* ContentView.swift */; };
|
||||
664BC12D26F0CA20007EE298 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664BC12C26F0CA20007EE298 /* Assets.xcassets */; };
|
||||
664BC13026F0CA20007EE298 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664BC12F26F0CA20007EE298 /* Preview Assets.xcassets */; };
|
||||
664BC13326F0CA20007EE298 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 664BC13126F0CA20007EE298 /* LaunchScreen.storyboard */; };
|
||||
664BC13B26F0CA94007EE298 /* AdvancedChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BC13A26F0CA94007EE298 /* AdvancedChat.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
664BC12326F0CA1F007EE298 /* AdvancedChat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AdvancedChat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
664BC12626F0CA1F007EE298 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
664BC12826F0CA1F007EE298 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
664BC12A26F0CA1F007EE298 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
664BC12C26F0CA20007EE298 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
664BC12F26F0CA20007EE298 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
664BC13226F0CA20007EE298 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
664BC13426F0CA20007EE298 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
664BC13A26F0CA94007EE298 /* AdvancedChat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedChat.swift; sourceTree = "<group>"; };
|
||||
8FCAA86A89E245EB7D78FAED /* Pods-AdvancedChat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AdvancedChat.debug.xcconfig"; path = "Target Support Files/Pods-AdvancedChat/Pods-AdvancedChat.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
9B4A3E0699D8A5E8F930E207 /* Pods-AdvancedChat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AdvancedChat.release.xcconfig"; path = "Target Support Files/Pods-AdvancedChat/Pods-AdvancedChat.release.xcconfig"; sourceTree = "<group>"; };
|
||||
E72FBDC953F141F267B03540 /* Pods_AdvancedChat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AdvancedChat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
664BC12026F0CA1F007EE298 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5F916A81CD75D10483A4DAC8 /* Pods_AdvancedChat.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
47B1E7CE04184A06D7C8479E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E72FBDC953F141F267B03540 /* Pods_AdvancedChat.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC11A26F0CA1F007EE298 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC12526F0CA1F007EE298 /* AdvancedChat */,
|
||||
664BC12426F0CA1F007EE298 /* Products */,
|
||||
D66D20255E37FA73AC508469 /* Pods */,
|
||||
47B1E7CE04184A06D7C8479E /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC12426F0CA1F007EE298 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC12326F0CA1F007EE298 /* AdvancedChat.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC12526F0CA1F007EE298 /* AdvancedChat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC12626F0CA1F007EE298 /* AppDelegate.swift */,
|
||||
664BC12826F0CA1F007EE298 /* SceneDelegate.swift */,
|
||||
664BC12A26F0CA1F007EE298 /* ContentView.swift */,
|
||||
664BC12C26F0CA20007EE298 /* Assets.xcassets */,
|
||||
664BC13126F0CA20007EE298 /* LaunchScreen.storyboard */,
|
||||
664BC13A26F0CA94007EE298 /* AdvancedChat.swift */,
|
||||
664BC13426F0CA20007EE298 /* Info.plist */,
|
||||
664BC12E26F0CA20007EE298 /* Preview Content */,
|
||||
);
|
||||
path = AdvancedChat;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
664BC12E26F0CA20007EE298 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
664BC12F26F0CA20007EE298 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D66D20255E37FA73AC508469 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8FCAA86A89E245EB7D78FAED /* Pods-AdvancedChat.debug.xcconfig */,
|
||||
9B4A3E0699D8A5E8F930E207 /* Pods-AdvancedChat.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
664BC12226F0CA1F007EE298 /* AdvancedChat */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 664BC13726F0CA20007EE298 /* Build configuration list for PBXNativeTarget "AdvancedChat" */;
|
||||
buildPhases = (
|
||||
70209B2F1633EA190EA8E09D /* [CP] Check Pods Manifest.lock */,
|
||||
664BC11F26F0CA1F007EE298 /* Sources */,
|
||||
664BC12026F0CA1F007EE298 /* Frameworks */,
|
||||
664BC12126F0CA1F007EE298 /* Resources */,
|
||||
16DC7246B49FC8754CAB12B5 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = AdvancedChat;
|
||||
productName = AdvancedChat;
|
||||
productReference = 664BC12326F0CA1F007EE298 /* AdvancedChat.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
664BC11B26F0CA1F007EE298 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1250;
|
||||
LastUpgradeCheck = 1250;
|
||||
TargetAttributes = {
|
||||
664BC12226F0CA1F007EE298 = {
|
||||
CreatedOnToolsVersion = 12.5.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 664BC11E26F0CA1F007EE298 /* Build configuration list for PBXProject "AdvancedChat" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 664BC11A26F0CA1F007EE298;
|
||||
productRefGroup = 664BC12426F0CA1F007EE298 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
664BC12226F0CA1F007EE298 /* AdvancedChat */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
664BC12126F0CA1F007EE298 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
664BC13326F0CA20007EE298 /* LaunchScreen.storyboard in Resources */,
|
||||
664BC13026F0CA20007EE298 /* Preview Assets.xcassets in Resources */,
|
||||
664BC12D26F0CA20007EE298 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
16DC7246B49FC8754CAB12B5 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-AdvancedChat/Pods-AdvancedChat-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-AdvancedChat/Pods-AdvancedChat-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AdvancedChat/Pods-AdvancedChat-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
70209B2F1633EA190EA8E09D /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-AdvancedChat-checkManifestLockResult.txt",
|
||||
);
|
||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
664BC11F26F0CA1F007EE298 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
664BC12726F0CA1F007EE298 /* AppDelegate.swift in Sources */,
|
||||
664BC12926F0CA1F007EE298 /* SceneDelegate.swift in Sources */,
|
||||
664BC12B26F0CA1F007EE298 /* ContentView.swift in Sources */,
|
||||
664BC13B26F0CA94007EE298 /* AdvancedChat.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
664BC13126F0CA20007EE298 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
664BC13226F0CA20007EE298 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
664BC13526F0CA20007EE298 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
664BC13626F0CA20007EE298 /* 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++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 14.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
664BC13826F0CA20007EE298 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 8FCAA86A89E245EB7D78FAED /* Pods-AdvancedChat.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"AdvancedChat/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = AdvancedChat/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.AdvancedChat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
664BC13926F0CA20007EE298 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9B4A3E0699D8A5E8F930E207 /* Pods-AdvancedChat.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"AdvancedChat/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = AdvancedChat/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = BC.AdvancedChat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
664BC11E26F0CA1F007EE298 /* Build configuration list for PBXProject "AdvancedChat" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
664BC13526F0CA20007EE298 /* Debug */,
|
||||
664BC13626F0CA20007EE298 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
664BC13726F0CA20007EE298 /* Build configuration list for PBXNativeTarget "AdvancedChat" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
664BC13826F0CA20007EE298 /* Debug */,
|
||||
664BC13926F0CA20007EE298 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 664BC11B26F0CA1F007EE298 /* Project object */;
|
||||
}
|
7
ios/swift/6-AdvancedChat/AdvancedChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/swift/6-AdvancedChat/AdvancedChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,8 @@
|
||||
<?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>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
276
ios/swift/6-AdvancedChat/AdvancedChat/AdvancedChat.swift
Normal file
276
ios/swift/6-AdvancedChat/AdvancedChat/AdvancedChat.swift
Normal file
@ -0,0 +1,276 @@
|
||||
//
|
||||
// GroupChat.swift
|
||||
// GroupChat
|
||||
//
|
||||
// Created by QuentinArguillere on 08/09/2021.
|
||||
// Copyright © 2021 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import linphonesw
|
||||
|
||||
|
||||
|
||||
class AdvancedChatTutorialContext : ObservableObject
|
||||
{
|
||||
var mCore: Core!
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
|
||||
var mRegistrationDelegate : CoreDelegate!
|
||||
@Published var username : String = "user"
|
||||
@Published var passwd : String = "pwd"
|
||||
@Published var domain : String = "sip.example.org"
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var transportType : String = "TLS"
|
||||
|
||||
/*------------ Advanced chat tutorial related variables -------*/
|
||||
var mChatroom : ChatRoom?
|
||||
var mChatroomDelegate : ChatRoomDelegate!
|
||||
var mChatMessageDelegate : ChatMessageDelegate!
|
||||
var mChatMessage : ChatMessage?
|
||||
var mLastFileMessageReceived : ChatMessage?
|
||||
@Published var msgToSend : String = "msg"
|
||||
@Published var remoteAddress : String = "sip:remote@sip.example.org"
|
||||
@Published var canEditAddress : Bool = true
|
||||
@Published var isDownloading : Bool = false
|
||||
@Published var messagesReceived : String = ""
|
||||
var fileFolderUrl : URL!
|
||||
var fileUrl : URL!
|
||||
|
||||
init()
|
||||
{
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
|
||||
try? mCore.start()
|
||||
|
||||
mRegistrationDelegate = CoreDelegateStub(onMessageReceived : { (core: Core, chatRoom: ChatRoom, message: ChatMessage) in
|
||||
if (self.mChatroom == nil) {
|
||||
// Check it is an one-to-one encrypted chat room
|
||||
if (chatRoom.hasCapability(mask: ChatRoomCapabilities.OneToOne.rawValue) &&
|
||||
chatRoom.hasCapability(mask: ChatRoomCapabilities.Encrypted.rawValue)) {
|
||||
// Keep the chatRoom object to use it to send messages if it hasn't been created yet
|
||||
self.mChatroom = chatRoom
|
||||
self.mChatroom!.addDelegate(delegate: self.mChatroomDelegate)
|
||||
self.enableEphemeral()
|
||||
if let remoteAddress = chatRoom.peerAddress?.asStringUriOnly() {
|
||||
self.remoteAddress = remoteAddress
|
||||
}
|
||||
self.canEditAddress = false
|
||||
}
|
||||
}
|
||||
|
||||
chatRoom.markAsRead()
|
||||
|
||||
for content in message.contents {
|
||||
if (content.isFileTransfer) {
|
||||
self.mLastFileMessageReceived = message
|
||||
self.messagesReceived += "\n--File available for download--"
|
||||
} else if (content.isText) {
|
||||
self.messagesReceived += "\nThem: \(message.utf8Text)"
|
||||
}
|
||||
}
|
||||
|
||||
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
mCore.addDelegate(delegate: mRegistrationDelegate)
|
||||
|
||||
// This delegate has to be attached to each specific chat message we want to monitor, before sending it
|
||||
mChatMessageDelegate = ChatMessageDelegateStub(onMsgStateChanged : { (message: ChatMessage, state: ChatMessage.State) in
|
||||
print("MessageTrace - msg state changed: \(state)\n")
|
||||
if (state == .InProgress) {
|
||||
|
||||
} else if (state == .Delivered) {
|
||||
// The proxy server has acknowledged the message with a 200 OK
|
||||
self.messagesReceived += "\nMe: \(message.utf8Text)"
|
||||
} else if (state == .DeliveredToUser) {
|
||||
// User has received it
|
||||
} else if (state == .Displayed) {
|
||||
// User has read it (client called chatRoom.markAsRead()
|
||||
} else if (state == .NotDelivered) {
|
||||
// User might be invalid or not registered
|
||||
} else if (state == .FileTransferDone && self.isDownloading == true) {
|
||||
// We finished uploading/downloading the file
|
||||
self.isDownloading = false
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
mChatroomDelegate = ChatRoomDelegateStub ( onStateChanged: { (chatRoom: ChatRoom, newState: ChatRoom.State?) in
|
||||
if (newState == ChatRoom.State.Created) {
|
||||
self.enableEphemeral()
|
||||
}
|
||||
}, onEphemeralEvent: { (chatRoom: ChatRoom, eventLog: EventLog) in
|
||||
// This event is generated when the chat room ephemeral settings are being changed
|
||||
}, onEphemeralMessageTimerStarted: { (chatRoom: ChatRoom, eventLog: EventLog) in
|
||||
// This is called when a message has been read by all recipient, so the timer has started
|
||||
}, onEphemeralMessageDeleted: { (chatRoom: ChatRoom, eventLog: EventLog) in
|
||||
// This is called when a message has expired and we should remove it from the view
|
||||
})
|
||||
|
||||
|
||||
// example file to send
|
||||
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
|
||||
fileFolderUrl = documentsPath.appendingPathComponent("TutorialFiles")
|
||||
fileUrl = fileFolderUrl?.appendingPathComponent("file_to_transfer.txt")
|
||||
do{
|
||||
try FileManager.default.createDirectory(atPath: fileFolderUrl!.path, withIntermediateDirectories: true, attributes: nil)
|
||||
try String("My file content").write(to: fileUrl!, atomically: false, encoding: .utf8)
|
||||
}catch let error as NSError{
|
||||
print("Unable to create d)irectory",error)
|
||||
}
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
do {
|
||||
var transport : TransportType
|
||||
if (transportType == "TLS") { transport = TransportType.Tls }
|
||||
else if (transportType == "TCP") { transport = TransportType.Tcp }
|
||||
else { transport = TransportType.Udp }
|
||||
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
let accountParams = try mCore.createAccountParams()
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try! accountParams.setIdentityaddress(newValue: identity)
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
accountParams.registerEnabled = true
|
||||
|
||||
// We need a conference factory URI set on the Account to be able to create chat rooms with flexisip backend
|
||||
accountParams.conferenceFactoryUri = "sip:conference-factory@sip.linphone.org"
|
||||
|
||||
mCore.addAuthInfo(info: authInfo)
|
||||
|
||||
let account = try mCore.createAccount(params: accountParams)
|
||||
try mCore.addAccount(account: account)
|
||||
mCore.defaultAccount = account
|
||||
|
||||
// We also need a LIME X3DH server URL configured for end to end encryption
|
||||
mCore.limeX3DhServerUrl = "https://lime.linphone.org/lime-server/lime-server.php"
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func unregister()
|
||||
{
|
||||
if let account = mCore.defaultAccount {
|
||||
let params = account.params
|
||||
let clonedParams = params?.clone()
|
||||
clonedParams?.registerEnabled = false
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
if let account = mCore.defaultAccount {
|
||||
mCore.removeAccount(account: account)
|
||||
mCore.clearAccounts()
|
||||
mCore.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func createFlexisipChatRoom() {
|
||||
do {
|
||||
// In this tutorial we will create a Flexisip one-to-one chat room with end-to-end encryption
|
||||
// For it to work, the proxy server we connect to must be an instance of Flexisip
|
||||
// And we must have configured on the Account a conference-factory URI
|
||||
let params = try mCore.createDefaultChatRoomParams()
|
||||
|
||||
// We won't create a group chat, only a 1-1 with advanced features such as end-to-end encryption
|
||||
params.backend = ChatRoomBackend.FlexisipChat
|
||||
params.groupEnabled = false
|
||||
|
||||
// We will rely on LIME encryption backend (we must have configured the core.limex3dhServerUrl first)
|
||||
params.encryptionEnabled = true
|
||||
params.encryptionBackend = ChatRoomEncryptionBackend.Lime
|
||||
|
||||
// A flexisip chat room must have a subject
|
||||
// But as we are doing a 1-1 chat room here we won't display it, so we can set whatever we want
|
||||
params.subject = "dummy subject"
|
||||
|
||||
if (params.isValid) {
|
||||
// We also need the SIP address of the person we will chat with
|
||||
let remote = try Factory.Instance.createAddress(addr: remoteAddress)
|
||||
|
||||
// And finally we will need our local SIP address
|
||||
let localAddress = mCore.defaultAccount?.params?.identityAddress
|
||||
mChatroom = try mCore.createChatRoom(params: params, localAddr: localAddress, participants: [remote])
|
||||
// If chat room isn't created yet, wait for it to go in state Created
|
||||
// as Flexisip chat room creation process is asynchronous
|
||||
mChatroom!.addDelegate(delegate: mChatroomDelegate)
|
||||
|
||||
// Chat room may already be created (for example if you logged in with an account for which the chat room already exists)
|
||||
if (mChatroom!.state == ChatRoom.State.Created) {
|
||||
enableEphemeral()
|
||||
canEditAddress = false
|
||||
}
|
||||
}
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func sendMessage() {
|
||||
do {
|
||||
if (mChatroom == nil) {
|
||||
createFlexisipChatRoom()
|
||||
}
|
||||
mChatMessage = nil
|
||||
mChatMessage = try mChatroom!.createMessageFromUtf8(message: msgToSend)
|
||||
mChatMessage!.addDelegate(delegate: mChatMessageDelegate)
|
||||
mChatMessage!.send()
|
||||
msgToSend.removeAll()
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func sendFile() {
|
||||
do {
|
||||
if (mChatroom == nil) {
|
||||
createFlexisipChatRoom()
|
||||
}
|
||||
|
||||
let content = try Factory.Instance.createContent()
|
||||
content.name = "file_to_transfer.txt"
|
||||
content.type = "text"
|
||||
content.subtype = "plain"
|
||||
content.filePath = fileUrl.path
|
||||
let chatMessage = try mChatroom!.createFileTransferMessage(initialContent: content)
|
||||
chatMessage.addDelegate(delegate: mChatMessageDelegate)
|
||||
mCore.fileTransferServer = "https://www.linphone.org:444/lft.php"
|
||||
chatMessage.send()
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
|
||||
func downloadLastFileMessage() {
|
||||
if let message = mLastFileMessageReceived {
|
||||
for content in message.contents {
|
||||
if (content.isFileTransfer && content.filePath.isEmpty) {
|
||||
let contentName = content.name
|
||||
if (!contentName.isEmpty) {
|
||||
content.filePath = fileFolderUrl!.appendingPathComponent(contentName).path
|
||||
print("Start downloading \(content.name) into \(content.filePath)")
|
||||
isDownloading = true
|
||||
if (!message.downloadContent(content: content)) {
|
||||
print ("Download of \(contentName) failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func enableEphemeral() {
|
||||
// Once chat room has been created, we can enable ephemeral feature
|
||||
// We enable ephemeral messages at the chat room level
|
||||
// Please note this only affects messages we send, not the ones we receive
|
||||
mChatroom?.ephemeralEnabled = true
|
||||
// Here we ask for a lifetime of 60 seconds, starting the moment the message has been read
|
||||
mChatroom?.ephemeralLifetime = 60
|
||||
}
|
||||
}
|
38
ios/swift/6-AdvancedChat/AdvancedChat/AppDelegate.swift
Normal file
38
ios/swift/6-AdvancedChat/AdvancedChat/AppDelegate.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// BasicChat
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@ObservedObject var tutorialContext = AdvancedChatTutorialContext()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: UISceneSession Lifecycle
|
||||
|
||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||
// Called when a new scene session is being created.
|
||||
// Use this method to select a configuration to create the new scene with.
|
||||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// Called when the user discards a scene session.
|
||||
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
144
ios/swift/6-AdvancedChat/AdvancedChat/ContentView.swift
Normal file
144
ios/swift/6-AdvancedChat/AdvancedChat/ContentView.swift
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// BasicChat
|
||||
//
|
||||
// Created by QuentinArguillere on 31/07/2020.
|
||||
// Copyright © 2020 BelledonneCommunications. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ActivityIndicator: UIViewRepresentable {
|
||||
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView
|
||||
{
|
||||
return UIActivityIndicatorView(style: .medium)
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>)
|
||||
{
|
||||
uiView.startAnimating()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView: View {
|
||||
|
||||
@ObservedObject var tutorialContext : AdvancedChatTutorialContext
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
Group {
|
||||
HStack {
|
||||
Text("Username:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.username)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Password:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.passwd)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
HStack {
|
||||
Text("Domain:")
|
||||
.font(.title)
|
||||
TextField("", text : $tutorialContext.domain)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(tutorialContext.loggedIn)
|
||||
}
|
||||
Picker(selection: $tutorialContext.transportType, label: Text("Transport:")) {
|
||||
Text("TLS").tag("TLS")
|
||||
Text("TCP").tag("TCP")
|
||||
Text("UDP").tag("UDP")
|
||||
}.pickerStyle(SegmentedPickerStyle()).padding()
|
||||
VStack {
|
||||
HStack {
|
||||
Button(action: {
|
||||
if (self.tutorialContext.loggedIn)
|
||||
{
|
||||
self.tutorialContext.unregister()
|
||||
self.tutorialContext.delete()
|
||||
} else {
|
||||
self.tutorialContext.login()
|
||||
}
|
||||
})
|
||||
{
|
||||
Text(tutorialContext.loggedIn ? "Log out & \ndelete account" : "Create & \nlog in account")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 220.0, height: 90)
|
||||
.background(Color.gray)
|
||||
}
|
||||
|
||||
}
|
||||
HStack {
|
||||
Text("Login State : ")
|
||||
.font(.footnote)
|
||||
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
|
||||
.font(.footnote)
|
||||
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
|
||||
}.padding(.top, 10.0)
|
||||
HStack {
|
||||
Text("Chat with:")
|
||||
TextField("", text : $tutorialContext.remoteAddress)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.disabled(!tutorialContext.canEditAddress)
|
||||
}
|
||||
Text("Chat received").bold()
|
||||
ScrollView {
|
||||
Text(tutorialContext.messagesReceived)
|
||||
.font(.footnote)
|
||||
.frame(width: 330, height: 400)
|
||||
}.border(Color.gray)
|
||||
HStack {
|
||||
TextField("Sent text", text : $tutorialContext.msgToSend)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
Button(action: tutorialContext.sendMessage)
|
||||
{
|
||||
Text("Send")
|
||||
.font(.callout)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 50.0, height: 30.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Button(action: tutorialContext.sendFile)
|
||||
{
|
||||
Text("Send example \n file")
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(width: 120.0, height: 50.0)
|
||||
.background(Color.gray)
|
||||
}
|
||||
Button(action: tutorialContext.downloadLastFileMessage)
|
||||
{
|
||||
Text("Download last files \n received")
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(width: 150.0, height: 50.0)
|
||||
.background(Color.gray)
|
||||
}.disabled(tutorialContext.mLastFileMessageReceived == nil)
|
||||
if (tutorialContext.isDownloading) {
|
||||
ActivityIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Group {
|
||||
Spacer()
|
||||
Text("Core Version is \(tutorialContext.coreVersion)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView(tutorialContext: AdvancedChatTutorialContext())
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user