From da6b391a46b08b28992c7f5fc37e8eaf73ccb2b1 Mon Sep 17 00:00:00 2001 From: Natalia Grankina Date: Thu, 14 Apr 2016 10:44:00 +0300 Subject: [PATCH] Camera kit initial commit --- .flowconfig | 89 ++ .gitignore | 34 + .watchmanconfig | 1 + android/app/build.gradle | 126 +++ android/app/proguard-rules.pro | 67 ++ android/app/react.gradle | 97 ++ android/app/src/main/AndroidManifest.xml | 23 + .../reactnativecamerakit/MainActivity.java | 40 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3418 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2206 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4842 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7718 bytes android/app/src/main/res/values/strings.xml | 3 + android/app/src/main/res/values/styles.xml | 8 + android/build.gradle | 24 + android/gradle.properties | 20 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 52266 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + android/gradlew | 164 ++++ android/gradlew.bat | 90 ++ android/settings.gradle | 3 + index.android.js | 51 + index.ios.js | 84 ++ ios/CameraSessionManager.swift | 183 ++++ ios/CameraViewController.swift | 385 ++++++++ ios/CameraViewControllerDelegate.swift | 13 + ios/CropHelper.swift | 58 ++ ios/PhotoViewController.swift | 78 ++ ios/PhotoViewControllerDelegate.swift | 12 + ios/Podfile | 13 + ios/Podfile.lock | 10 + .../AnimationController.swift | 80 ++ .../ImagePickerAction.swift | 75 ++ .../ImagePickerSheetController.swift | 482 ++++++++++ .../Images.xcassets/Contents.json | 6 + .../Contents.json | 23 + .../PreviewCollectionViewCell-video.png | Bin 0 -> 262 bytes .../PreviewCollectionViewCell-video@2x.png | Bin 0 -> 413 bytes .../PreviewCollectionViewCell-video@3x.png | Bin 0 -> 544 bytes .../Contents.json | 23 + ...ewSupplementaryView-Checkmark-Selected.png | Bin 0 -> 713 bytes ...upplementaryView-Checkmark-Selected@2x.png | Bin 0 -> 1566 bytes ...upplementaryView-Checkmark-Selected@3x.png | Bin 0 -> 2423 bytes .../Contents.json | 23 + .../PreviewSupplementaryView-Checkmark.png | Bin 0 -> 629 bytes .../PreviewSupplementaryView-Checkmark@2x.png | Bin 0 -> 1394 bytes .../PreviewSupplementaryView-Checkmark@3x.png | Bin 0 -> 2136 bytes .../Sheet/Preview/PreviewCollectionView.swift | 56 ++ .../Preview/PreviewCollectionViewCell.swift | 75 ++ .../Preview/PreviewCollectionViewLayout.swift | 156 +++ .../Preview/PreviewSupplementaryView.swift | 92 ++ .../Sheet/SheetActionCollectionViewCell.swift | 70 ++ .../Sheet/SheetCollectionViewCell.swift | 173 ++++ .../Sheet/SheetCollectionViewLayout.swift | 99 ++ .../Sheet/SheetController.swift | 265 ++++++ .../SheetPreviewCollectionViewCell.swift | 39 + ios/Pods/ImagePickerSheetController/LICENSE | 21 + ios/Pods/ImagePickerSheetController/README.md | 56 ++ ios/Pods/Manifest.lock | 10 + ios/Pods/Pods.xcodeproj/project.pbxproj | 573 +++++++++++ .../ImagePickerSheetController-dummy.m | 5 + .../ImagePickerSheetController-prefix.pch | 4 + .../ImagePickerSheetController-umbrella.h | 6 + .../ImagePickerSheetController.modulemap | 6 + .../ImagePickerSheetController.xcconfig | 6 + .../ImagePickerSheetController/Info.plist | 26 + .../Pods-ReactNativeCameraKit/Info.plist | 26 + ...tNativeCameraKit-acknowledgements.markdown | 28 + ...eactNativeCameraKit-acknowledgements.plist | 58 ++ .../Pods-ReactNativeCameraKit-dummy.m | 5 + .../Pods-ReactNativeCameraKit-frameworks.sh | 91 ++ .../Pods-ReactNativeCameraKit-resources.sh | 95 ++ .../Pods-ReactNativeCameraKit-umbrella.h | 6 + .../Pods-ReactNativeCameraKit.debug.xcconfig | 8 + .../Pods-ReactNativeCameraKit.modulemap | 6 + ...Pods-ReactNativeCameraKit.release.xcconfig | 8 + ios/ReactNativeCameraKit-Bridging-Header.h | 4 + ios/ReactNativeCameraKit.m | 16 + ios/ReactNativeCameraKit.swift | 170 ++++ .../project.pbxproj | 901 ++++++++++++++++++ .../xcschemes/ReactNativeCameraKit.xcscheme | 112 +++ .../contents.xcworkspacedata | 10 + ios/ReactNativeCameraKit/AppDelegate.h | 16 + ios/ReactNativeCameraKit/AppDelegate.m | 59 ++ .../Base.lproj/LaunchScreen.xib | 42 + .../AppIcon.appiconset/Contents.json | 38 + .../CloseIcon.imageset/Contents.json | 23 + .../CloseIcon.imageset/Delete-1.png | Bin 0 -> 8101 bytes .../CloseIcon.imageset/Delete-2.png | Bin 0 -> 8101 bytes .../CloseIcon.imageset/Delete.png | Bin 0 -> 8101 bytes .../FlashAutoIcon.imageset/Contents.json | 23 + .../flash_on_filled-25.png | Bin 0 -> 475 bytes .../flash_on_filled-50.png | Bin 0 -> 633 bytes .../flash_on_filled-75.png | Bin 0 -> 946 bytes .../FlashOffIcon.imageset/Contents.json | 23 + .../flash_off_filled-25.png | Bin 0 -> 541 bytes .../flash_off_filled-50.png | Bin 0 -> 734 bytes .../flash_off_filled-75.png | Bin 0 -> 1108 bytes .../FlashOnIcon.imageset/Contents.json | 23 + .../flash_on_filled-25.png | Bin 0 -> 584 bytes .../flash_on_filled-50.png | Bin 0 -> 812 bytes .../flash_on_filled-75.png | Bin 0 -> 1051 bytes .../ShutterIcon.imageset/Contents.json | 23 + .../Shutter-Release-1.jpg | Bin 0 -> 14810 bytes .../Shutter-Release-2.jpg | Bin 0 -> 14810 bytes .../ShutterIcon.imageset/Shutter-Release.jpg | Bin 0 -> 14810 bytes ios/ReactNativeCameraKit/Info.plist | 47 + ios/ReactNativeCameraKit/main.m | 18 + ios/ReactNativeCameraKitTests/Info.plist | 24 + .../ReactNativeCameraKitTests.m | 70 ++ package.json | 12 + 111 files changed, 6116 insertions(+) create mode 100644 .flowconfig create mode 100644 .gitignore create mode 100644 .watchmanconfig create mode 100644 android/app/build.gradle create mode 100644 android/app/proguard-rules.pro create mode 100644 android/app/react.gradle create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/java/com/reactnativecamerakit/MainActivity.java create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values/strings.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100755 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/settings.gradle create mode 100644 index.android.js create mode 100644 index.ios.js create mode 100644 ios/CameraSessionManager.swift create mode 100644 ios/CameraViewController.swift create mode 100644 ios/CameraViewControllerDelegate.swift create mode 100644 ios/CropHelper.swift create mode 100644 ios/PhotoViewController.swift create mode 100644 ios/PhotoViewControllerDelegate.swift create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/AnimationController.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerAction.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/Contents.json create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/Contents.json create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video@2x.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video@3x.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/Contents.json create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected@2x.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected@3x.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/Contents.json create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark@2x.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark@3x.png create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionView.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewCell.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewLayout.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewSupplementaryView.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetActionCollectionViewCell.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewCell.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewLayout.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetController.swift create mode 100644 ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetPreviewCollectionViewCell.swift create mode 100644 ios/Pods/ImagePickerSheetController/LICENSE create mode 100644 ios/Pods/ImagePickerSheetController/README.md create mode 100644 ios/Pods/Manifest.lock create mode 100644 ios/Pods/Pods.xcodeproj/project.pbxproj create mode 100644 ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-dummy.m create mode 100644 ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-prefix.pch create mode 100644 ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-umbrella.h create mode 100644 ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.modulemap create mode 100644 ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.xcconfig create mode 100644 ios/Pods/Target Support Files/ImagePickerSheetController/Info.plist create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Info.plist create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.markdown create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.plist create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-dummy.m create mode 100755 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-frameworks.sh create mode 100755 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-resources.sh create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-umbrella.h create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.debug.xcconfig create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.modulemap create mode 100644 ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.release.xcconfig create mode 100644 ios/ReactNativeCameraKit-Bridging-Header.h create mode 100644 ios/ReactNativeCameraKit.m create mode 100644 ios/ReactNativeCameraKit.swift create mode 100644 ios/ReactNativeCameraKit.xcodeproj/project.pbxproj create mode 100644 ios/ReactNativeCameraKit.xcodeproj/xcshareddata/xcschemes/ReactNativeCameraKit.xcscheme create mode 100644 ios/ReactNativeCameraKit.xcworkspace/contents.xcworkspacedata create mode 100644 ios/ReactNativeCameraKit/AppDelegate.h create mode 100644 ios/ReactNativeCameraKit/AppDelegate.m create mode 100644 ios/ReactNativeCameraKit/Base.lproj/LaunchScreen.xib create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Contents.json create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete-1.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete-2.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/Contents.json create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-25.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-50.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-75.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/Contents.json create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-25.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-50.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-75.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOnIcon.imageset/Contents.json create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOnIcon.imageset/flash_on_filled-25.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOnIcon.imageset/flash_on_filled-50.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/FlashOnIcon.imageset/flash_on_filled-75.png create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/ShutterIcon.imageset/Contents.json create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/ShutterIcon.imageset/Shutter-Release-1.jpg create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/ShutterIcon.imageset/Shutter-Release-2.jpg create mode 100644 ios/ReactNativeCameraKit/Images.xcassets/ShutterIcon.imageset/Shutter-Release.jpg create mode 100644 ios/ReactNativeCameraKit/Info.plist create mode 100644 ios/ReactNativeCameraKit/main.m create mode 100644 ios/ReactNativeCameraKitTests/Info.plist create mode 100644 ios/ReactNativeCameraKitTests/ReactNativeCameraKitTests.m create mode 100644 package.json diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..66b57e0 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,89 @@ +[ignore] + +# We fork some components by platform. +.*/*.web.js +.*/*.android.js + +# Some modules have their own node_modules with overlap +.*/node_modules/node-haste/.* + +# Ugh +.*/node_modules/babel.* +.*/node_modules/babylon.* +.*/node_modules/invariant.* + +# Ignore react and fbjs where there are overlaps, but don't ignore +# anything that react-native relies on +.*/node_modules/fbjs/lib/Map.js +.*/node_modules/fbjs/lib/fetch.js +.*/node_modules/fbjs/lib/ExecutionEnvironment.js +.*/node_modules/fbjs/lib/ErrorUtils.js + +# Flow has a built-in definition for the 'react' module which we prefer to use +# over the currently-untyped source +.*/node_modules/react/react.js +.*/node_modules/react/lib/React.js +.*/node_modules/react/lib/ReactDOM.js + +.*/__mocks__/.* +.*/__tests__/.* + +.*/commoner/test/source/widget/share.js + +# Ignore commoner tests +.*/node_modules/commoner/test/.* + +# See https://github.com/facebook/flow/issues/442 +.*/react-tools/node_modules/commoner/lib/reader.js + +# Ignore jest +.*/node_modules/jest-cli/.* + +# Ignore Website +.*/website/.* + +.*/node_modules/is-my-json-valid/test/.*\.json +.*/node_modules/iconv-lite/encodings/tables/.*\.json +.*/node_modules/y18n/test/.*\.json +.*/node_modules/spdx-license-ids/spdx-license-ids.json +.*/node_modules/spdx-exceptions/index.json +.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json +.*/node_modules/resolve/lib/core.json +.*/node_modules/jsonparse/samplejson/.*\.json +.*/node_modules/json5/test/.*\.json +.*/node_modules/ua-parser-js/test/.*\.json +.*/node_modules/builtin-modules/builtin-modules.json +.*/node_modules/binary-extensions/binary-extensions.json +.*/node_modules/url-regex/tlds.json +.*/node_modules/joi/.*\.json +.*/node_modules/isemail/.*\.json +.*/node_modules/tr46/.*\.json + +[include] + +[libs] +node_modules/react-native/Libraries/react-native/react-native-interface.js +node_modules/react-native/flow +flow/ + +[options] +module.system=haste + +esproposal.class_static_fields=enable +esproposal.class_instance_fields=enable + +munge_underscores=true + +module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FixMe + +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-2]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-2]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy + +[version] +0.22.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..94fc867 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + +# Android/IJ +# +.idea +.gradle +local.properties + +# node.js +# +node_modules/ +npm-debug.log diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..7934101 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,126 @@ +apply plugin: "com.android.application" + +import com.android.build.OutputFile + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation + * entryFile: "index.android.js", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property can be in the following formats + * // 'bundleIn${productFlavor}${buildType}' + * // 'bundleIn${buildType}' + * // bundleInFreeDebug: true, + * // bundleInPaidRelease: true, + * // bundleInBeta: true, + * + * // the root of your project, i.e. where "package.json" lives + * root: "../../", + * + * // where to put the JS bundle asset in debug mode + * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", + * + * // where to put the JS bundle asset in release mode + * jsBundleDirRelease: "$buildDir/intermediates/assets/release", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in debug mode + * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in release mode + * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", + * + * // by default the gradle tasks are skipped if none of the JS files or assets change; this means + * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to + * // date; if you have any other folders that you want to ignore for performance reasons (gradle + * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ + * // for example, you might want to remove it from here. + * inputExcludes: ["android/**", "ios/**"] + * ] + */ + +apply from: "react.gradle" + +/** + * Set this to true to create two separate APKs instead of one: + * - An APK that only works on ARM devices + * - An APK that only works on x86 devices + * The advantage is the size of the APK is reduced by about 4MB. + * Upload all the APKs to the Play Store and people will download + * the correct one based on the CPU architecture of their device. + */ +def enableSeparateBuildPerCPUArchitecture = false + +/** + * Run Proguard to shrink the Java bytecode in release builds. + */ +def enableProguardInReleaseBuilds = false + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.1" + + defaultConfig { + applicationId "com.reactnativecamerakit" + minSdkVersion 16 + targetSdkVersion 22 + versionCode 1 + versionName "1.0" + ndk { + abiFilters "armeabi-v7a", "x86" + } + } + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include "armeabi-v7a", "x86" + } + } + buildTypes { + release { + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits + def versionCodes = ["armeabi-v7a":1, "x86":2] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + versionCodes.get(abi) * 1048576 + defaultConfig.versionCode + } + } + } +} + +dependencies { + compile fileTree(dir: "libs", include: ["*.jar"]) + compile "com.android.support:appcompat-v7:23.0.1" + compile "com.facebook.react:react-native:+" // From node_modules +} diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000..7d72e46 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,67 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Disabling obfuscation is useful if you collect stack traces from production crashes +# (unless you are using a system that supports de-obfuscate the stack traces). +-dontobfuscate + +# React Native + +# Keep our interfaces so they can be used by other ProGuard rules. +# See http://sourceforge.net/p/proguard/bugs/466/ +-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip +-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters + +# Do not strip any method/class that is annotated with @DoNotStrip +-keep @com.facebook.proguard.annotations.DoNotStrip class * +-keepclassmembers class * { + @com.facebook.proguard.annotations.DoNotStrip *; +} + +-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { + void set*(***); + *** get*(); +} + +-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } +-keep class * extends com.facebook.react.bridge.NativeModule { *; } +-keepclassmembers,includedescriptorclasses class * { native ; } +-keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } +-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } +-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } + +-dontwarn com.facebook.react.** + +# okhttp + +-keepattributes Signature +-keepattributes *Annotation* +-keep class com.squareup.okhttp.** { *; } +-keep interface com.squareup.okhttp.** { *; } +-dontwarn com.squareup.okhttp.** + +# okio + +-keep class sun.misc.Unsafe { *; } +-dontwarn java.nio.file.* +-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement +-dontwarn okio.** + +# stetho + +-dontwarn com.facebook.stetho.** diff --git a/android/app/react.gradle b/android/app/react.gradle new file mode 100644 index 0000000..850e40d --- /dev/null +++ b/android/app/react.gradle @@ -0,0 +1,97 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +def config = project.hasProperty("react") ? project.react : []; + +def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" +def entryFile = config.entryFile ?: "index.android.js" + +// because elvis operator +def elvisFile(thing) { + return thing ? file(thing) : null; +} + +def reactRoot = elvisFile(config.root) ?: file("../../") +def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] + +void runBefore(String dependentTaskName, Task task) { + Task dependentTask = tasks.findByPath(dependentTaskName); + if (dependentTask != null) { + dependentTask.dependsOn task + } +} + +gradle.projectsEvaluated { + // Grab all build types and product flavors + def buildTypes = android.buildTypes.collect { type -> type.name } + def productFlavors = android.productFlavors.collect { flavor -> flavor.name } + + // When no product flavors defined, use empty + if (!productFlavors) productFlavors.add('') + + productFlavors.each { productFlavorName -> + buildTypes.each { buildTypeName -> + // Create variant and target names + def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}" + def targetPath = productFlavorName ? + "${productFlavorName}/${buildTypeName}" : + "${buildTypeName}" + + // React js bundle directories + def jsBundleDirConfigName = "jsBundleDir${targetName}" + def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: + file("$buildDir/intermediates/assets/${targetPath}") + + def resourcesDirConfigName = "resourcesDir${targetName}" + def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?: + file("$buildDir/intermediates/res/merged/${targetPath}") + def jsBundleFile = file("$jsBundleDir/$bundleAssetName") + + // Bundle task name for variant + def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets" + + def currentBundleTask = tasks.create( + name: bundleJsAndAssetsTaskName, + type: Exec) { + group = "react" + description = "bundle JS and assets for ${targetName}." + + // Create dirs if they are not there (e.g. the "clean" task just ran) + doFirst { + jsBundleDir.mkdirs() + resourcesDir.mkdirs() + } + + // Set up inputs and outputs so gradle can cache the result + inputs.files fileTree(dir: reactRoot, excludes: inputExcludes) + outputs.dir jsBundleDir + outputs.dir resourcesDir + + // Set up the call to the react-native cli + workingDir reactRoot + + // Set up dev mode + def devEnabled = !targetName.toLowerCase().contains("release") + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine "cmd", "/c", "node", "node_modules/react-native/local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}", + "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir + } else { + commandLine "node", "node_modules/react-native/local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}", + "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir + } + + enabled config."bundleIn${targetName}" || + config."bundleIn${buildTypeName.capitalize()}" ?: + targetName.toLowerCase().contains("release") + } + + // Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process + currentBundleTask.dependsOn("merge${targetName}Resources") + currentBundleTask.dependsOn("merge${targetName}Assets") + + runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask) + runBefore("processX86${targetName}Resources", currentBundleTask) + runBefore("processUniversal${targetName}Resources", currentBundleTask) + runBefore("process${targetName}Resources", currentBundleTask) + } + } +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6652a54 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/com/reactnativecamerakit/MainActivity.java b/android/app/src/main/java/com/reactnativecamerakit/MainActivity.java new file mode 100644 index 0000000..68ee5e4 --- /dev/null +++ b/android/app/src/main/java/com/reactnativecamerakit/MainActivity.java @@ -0,0 +1,40 @@ +package com.reactnativecamerakit; + +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactPackage; +import com.facebook.react.shell.MainReactPackage; + +import java.util.Arrays; +import java.util.List; + +public class MainActivity extends ReactActivity { + + /** + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "ReactNativeCameraKit"; + } + + /** + * Returns whether dev mode should be enabled. + * This enables e.g. the dev menu. + */ + @Override + protected boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + /** + * A list of packages used by the app. If the app uses additional views + * or modules besides the default ones, add more packages here. + */ + @Override + protected List getPackages() { + return Arrays.asList( + new MainReactPackage() + ); + } +} diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..cde69bcccec65160d92116f20ffce4fce0b5245c GIT binary patch literal 3418 zcmZ{nX*|@A^T0p5j$I+^%FVhdvMbgt%d+mG98ubwNv_tpITppba^GiieBBZGI>I89 zGgm8TA>_)DlEu&W;s3#ZUNiH4&CF{a%siTjzG;eOzQB6{003qKeT?}z_5U*{{kgZ; zdV@U&tqa-&4FGisjMN8o=P}$t-`oTM2oeB5d9mHPgTYJx4jup)+5a;Tke$m708DocFzDL>U$$}s6FGiy_I1?O zHXq`q884|^O4Q*%V#vwxqCz-#8i`Gu)2LeB0{%%VKunOF%9~JcFB9MM>N00M`E~;o zBU%)O5u-D6NF~OQV7TV#JAN;=Lylgxy0kncoQpGq<<_gxw`FC=C-cV#$L|(47Hatl ztq3Jngq00x#}HGW@_tj{&A?lwOwrVX4@d66vLVyj1H@i}VD2YXd)n03?U5?cKtFz4 zW#@+MLeDVP>fY0F2IzT;r5*MAJ2}P8Z{g3utX0<+ZdAC)Tvm-4uN!I7|BTw&G%RQn zR+A5VFx(}r<1q9^N40XzP=Jp?i=jlS7}T~tB4CsWx!XbiHSm zLu}yar%t>-3jlutK=wdZhES->*1X({YI;DN?6R=C*{1U6%wG`0>^?u}h0hhqns|SeTmV=s;Gxx5F9DtK>{>{f-`SpJ`dO26Ujk?^%ucsuCPe zIUk1(@I3D^7{@jmXO2@<84|}`tDjB}?S#k$ik;jC))BH8>8mQWmZ zF#V|$gW|Xc_wmmkoI-b5;4AWxkA>>0t4&&-eC-J_iP(tLT~c6*(ZnSFlhw%}0IbiJ ztgnrZwP{RBd(6Ds`dM~k;rNFgkbU&Yo$KR#q&%Kno^YXF5ONJwGwZ*wEr4wYkGiXs z$&?qX!H5sV*m%5t@3_>ijaS5hp#^Pu>N_9Q?2grdNp({IZnt|P9Xyh);q|BuoqeUJ zfk(AGX4odIVADHEmozF|I{9j>Vj^jCU}K)r>^%9#E#Y6B0i#f^iYsNA!b|kVS$*zE zx7+P?0{oudeZ2(ke=YEjn#+_cdu_``g9R95qet28SG>}@Me!D6&}un*e#CyvlURrg8d;i$&-0B?4{eYEgzwotp*DOQ_<=Ai21Kzb0u zegCN%3bdwxj!ZTLvBvexHmpTw{Z3GRGtvkwEoKB1?!#+6h1i2JR%4>vOkPN_6`J}N zk}zeyY3dPV+IAyn;zRtFH5e$Mx}V(|k+Ey#=nMg-4F#%h(*nDZDK=k1snlh~Pd3dA zV!$BoX_JfEGw^R6Q2kpdKD_e0m*NX?M5;)C zb3x+v?J1d#jRGr=*?(7Habkk1F_#72_iT7{IQFl<;hkqK83fA8Q8@(oS?WYuQd4z^ z)7eB?N01v=oS47`bBcBnKvI&)yS8`W8qHi(h2na?c6%t4mU(}H(n4MO zHIpFdsWql()UNTE8b=|ZzY*>$Z@O5m9QCnhOiM%)+P0S06prr6!VET%*HTeL4iu~!y$pN!mOo5t@1 z?$$q-!uP(+O-%7<+Zn5i=)2OftC+wOV;zAU8b`M5f))CrM6xu94e2s78i&zck@}%= zZq2l!$N8~@63!^|`{<=A&*fg;XN*7CndL&;zE(y+GZVs-IkK~}+5F`?ergDp=9x1w z0hkii!N(o!iiQr`k`^P2LvljczPcM`%7~2n#|K7nJq_e0Ew;UsXV_~3)<;L?K9$&D zUzgUOr{C6VLl{Aon}zp`+fH3>$*~swkjCw|e>_31G<=U0@B*~hIE)|WSb_MaE41Prxp-2eEg!gcon$fN6Ctl7A_lV8^@B9B+G~0=IYgc%VsprfC`e zoBn&O3O)3MraW#z{h3bWm;*HPbp*h+I*DoB%Y~(Fqp9+x;c>K2+niydO5&@E?SoiX_zf+cI09%%m$y=YMA~rg!xP*>k zmYxKS-|3r*n0J4y`Nt1eO@oyT0Xvj*E3ssVNZAqQnj-Uq{N_&3e45Gg5pna+r~Z6^ z>4PJ7r(gO~D0TctJQyMVyMIwmzw3rbM!};>C@8JA<&6j3+Y9zHUw?tT_-uNh^u@np zM?4qmcc4MZjY1mWLK!>1>7uZ*%Pe%=DV|skj)@OLYvwGXuYBoZvbB{@l}cHK!~UHm z4jV&m&uQAOLsZUYxORkW4|>9t3L@*ieU&b0$sAMH&tKidc%;nb4Z=)D7H<-`#%$^# zi`>amtzJ^^#zB2e%o*wF!gZBqML9>Hq9jqsl-|a}yD&JKsX{Op$7)_=CiZvqj;xN& zqb@L;#4xW$+icPN?@MB|{I!>6U(h!Wxa}14Z0S&y|A5$zbH(DXuE?~WrqNv^;x}vI z0PWfSUuL7Yy``H~*?|%z zT~ZWYq}{X;q*u-}CT;zc_NM|2MKT8)cMy|d>?i^^k)O*}hbEcCrU5Bk{Tjf1>$Q=@ zJ9=R}%vW$~GFV_PuXqE4!6AIuC?Tn~Z=m#Kbj3bUfpb82bxsJ=?2wL>EGp=wsj zAPVwM=CffcycEF; z@kPngVDwPM>T-Bj4##H9VONhbq%=SG;$AjQlV^HOH7!_vZk=}TMt*8qFI}bI=K9g$fgD9$! zO%cK1_+Wbk0Ph}E$BR2}4wO<_b0{qtIA1ll>s*2^!7d2e`Y>$!z54Z4FmZ*vyO}EP z@p&MG_C_?XiKBaP#_XrmRYszF;Hyz#2xqG%yr991pez^qN!~gT_Jc=PPCq^8V(Y9K zz33S+Mzi#$R}ncqe!oJ3>{gacj44kx(SOuC%^9~vT}%7itrC3b;ZPfX;R`D2AlGgN zw$o4-F77!eWU0$?^MhG9zxO@&zDcF;@w2beXEa3SL^htWYY{5k?ywyq7u&)~Nys;@ z8ZNIzUw$#ci&^bZ9mp@A;7y^*XpdWlzy%auO1hU=UfNvfHtiPM@+99# z!uo2`>!*MzphecTjN4x6H)xLeeDVEO#@1oDp`*QsBvmky=JpY@fC0$yIexO%f>c-O zAzUA{ch#N&l;RClb~;`@dqeLPh?e-Mr)T-*?Sr{32|n(}m>4}4c3_H3*U&Yj)grth z{%F0z7YPyjux9hfqa+J|`Y%4gwrZ_TZCQq~0wUR8}9@Jj4lh( z#~%AcbKZ++&f1e^G8LPQ)*Yy?lp5^z4pDTI@b^hlv06?GC%{ZywJcy}3U@zS3|M{M zGPp|cq4Zu~9o_cEZiiNyU*tc73=#Mf>7uzue|6Qo_e!U;oJ)Z$DP~(hOcRy&hR{`J zP7cNIgc)F%E2?p%{%&sxXGDb0yF#zac5fr2x>b)NZz8prv~HBhw^q=R$nZ~@&zdBi z)cEDu+cc1?-;ZLm?^x5Ov#XRhw9{zr;Q#0*wglhWD={Pn$Qm$;z?Vx)_f>igNB!id zmTlMmkp@8kP212#@jq=m%g4ZEl$*a_T;5nHrbt-6D0@eqFP7u+P`;X_Qk68bzwA0h zf{EW5xAV5fD)il-cV&zFmPG|KV4^Z{YJe-g^>uL2l7Ep|NeA2#;k$yerpffdlXY<2 znDODl8(v(24^8Cs3wr(UajK*lY*9yAqcS>92eF=W8<&GtU-}>|S$M5}kyxz~p>-~Pb{(irc?QF~icx8A201&Xin%Hxx@kekd zw>yHjlemC*8(JFz05gs6x7#7EM|xoGtpVVs0szqB0bqwaqAdVG7&rLc6#(=y0YEA! z=jFw}xeKVfmAMI*+}bv7qH=LK2#X5^06wul0s+}M(f|O@&WMyG9frlGyLb z&Eix=47rL84J+tEWcy_XTyc*xw9uOQy`qmHCjAeJ?d=dUhm;P}^F=LH42AEMIh6X8 z*I7Q1jK%gVlL|8w?%##)xSIY`Y+9$SC8!X*_A*S0SWOKNUtza(FZHahoC2|6f=*oD zxJ8-RZk!+YpG+J}Uqnq$y%y>O^@e5M3SSw^29PMwt%8lX^9FT=O@VX$FCLBdlj#<{ zJWWH<#iU!^E7axvK+`u;$*sGq1SmGYc&{g03Md&$r@btQSUIjl&yJXA&=79FdJ+D< z4K^ORdM{M0b2{wRROvjz1@Rb>5dFb@gfkYiIOAKM(NR3*1JpeR_Hk3>WGvU&>}D^HXZ02JUnM z@1s_HhX#rG7;|FkSh2#agJ_2fREo)L`ws+6{?IeWV(>Dy8A(6)IjpSH-n_uO=810y z#4?ez9NnERv6k)N13sXmx)=sv=$$i_QK`hp%I2cyi*J=ihBWZLwpx9Z#|s;+XI!0s zLjYRVt!1KO;mnb7ZL~XoefWU02f{jcY`2wZ4QK+q7gc4iz%d0)5$tPUg~$jVI6vFO zK^wG7t=**T40km@TNUK+WTx<1mL|6Tn6+kB+E$Gpt8SauF9E-CR9Uui_EHn_nmBqS z>o#G}58nHFtICqJPx<_?UZ;z0_(0&UqMnTftMKW@%AxYpa!g0fxGe060^xkRtYguj ze&fPtC!?RgE}FsE0*^2lnE>42K#jp^nJDyzp{JV*jU?{+%KzW37-q|d3i&%eooE6C8Z2t2 z9bBL;^fzVhdLxCQh1+Ms5P)ilz9MYFKdqYN%*u^ch(Fq~QJASr5V_=szAKA4Xm5M} z(Kka%r!noMtz6ZUbjBrJ?Hy&c+mHB{OFQ}=41Irej{0N90`E*~_F1&7Du+zF{Dky) z+KN|-mmIT`Thcij!{3=ibyIn830G zN{kI3d`NgUEJ|2If}J!?@w~FV+v?~tlo8ps3Nl`3^kI)WfZ0|ms6U8HEvD9HIDWkz6`T_QSewYZyzkRh)!g~R>!jaR9;K|#82kfE5^;R!~}H4C?q{1AG?O$5kGp)G$f%VML%aPD?{ zG6)*KodSZRXbl8OD=ETxQLJz)KMI7xjArKUNh3@0f|T|75?Yy=pD7056ja0W)O;Td zCEJ=7q?d|$3rZb+8Cvt6mybV-#1B2}Jai^DOjM2<90tpql|M5tmheg){2NyZR}x3w zL6u}F+C-PIzZ56q0x$;mVJXM1V0;F}y9F29ob51f;;+)t&7l30gloMMHPTuod530FC}j^4#qOJV%5!&e!H9#!N&XQvs5{R zD_FOomd-uk@?_JiWP%&nQ_myBlM6so1Ffa1aaL7B`!ZTXPg_S%TUS*>M^8iJRj1*~ e{{%>Z1YfTk|3C04d;8A^0$7;Zm{b|L#{L(;l>}-4 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..bfa42f0e7b91d006d22352c9ff2f134e504e3c1d GIT binary patch literal 4842 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..324e72cdd7480cb983fa1bcc7ce686e51ef87fe7 GIT binary patch literal 7718 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e80bed5 --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + ReactNativeCameraKit + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..319eb0c --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..403a007 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,24 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.3.1' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + mavenLocal() + jcenter() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$projectDir/../../node_modules/react-native/android" + } + } +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..1fd964e --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +android.useDeprecatedNdk=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..b5166dad4d90021f6a0b45268c0755719f1d5cd4 GIT binary patch literal 52266 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 z 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 literal 0 HcmV?d00001 diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b9fbfab --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 0000000..91a7e26 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..9237993 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = 'ReactNativeCameraKit' + +include ':app' diff --git a/index.android.js b/index.android.js new file mode 100644 index 0000000..94b42e0 --- /dev/null +++ b/index.android.js @@ -0,0 +1,51 @@ +/** + * Sample React Native App + * https://github.com/facebook/react-native + */ + +import React, { + AppRegistry, + Component, + StyleSheet, + Text, + View +} from 'react-native'; + +class ReactNativeCameraKit extends Component { + render() { + return ( + + + Welcome to React Native! + + + To get started, edit index.android.js + + + Shake or press menu button for dev menu + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + welcome: { + fontSize: 20, + textAlign: 'center', + margin: 10, + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, +}); + +AppRegistry.registerComponent('ReactNativeCameraKit', () => ReactNativeCameraKit); diff --git a/index.ios.js b/index.ios.js new file mode 100644 index 0000000..6f710cd --- /dev/null +++ b/index.ios.js @@ -0,0 +1,84 @@ +import React from 'react-native'; + +const { + AppRegistry, + Component, + StyleSheet, + Text, + View, + Image, + TouchableOpacity, + PixelRatio, + NativeModules: { + ReactNativeCameraKit + } + } = React; + +class Example extends Component { + state = { + photoSource: null, + error: null + }; + + selectPhotoTapped() { + const options = { + message: 'Recent Images', + takePhotoActionTitle: 'Take a Photo', + pickPhotoActionTitle: 'Gallery', + cancelActionTitle: 'Cancel', + sendSelectedPhotosTitle: 'Send %lu Photo', + aspectRatioInfoMessage: 'Your images look best with 16:9 ratio', + aspectRatios: ["16:9", "1:1", "4:3", "3:2", "2:3", "3:4", "9:16"], + collectionName: 'eCom' + }; + + ReactNativeCameraKit.presentPhotoPicker(options, (response) => { + if (response.images) { + const source = {uri: 'data:image/jpeg;base64,' + response.images[response.images.length -1], isStatic: true}; + this.setState({ + photoSource: source + }); + } + if (response.error) { + this.setState({ + error: response.error + }); + } + }); + } + render() { + return ( + + + +{ this.state.photoSource === null ? Select a Photo : + +} + +{ this.state.error ? this.state.error : null } + + +); +} +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF' + }, + photoContainer: { + borderColor: '#9B9B9B', + justifyContent: 'center', + alignItems: 'center', + borderWidth: 1 / PixelRatio.get() + }, + photo: { + width: 150, + height: 150 + } +}); + +AppRegistry.registerComponent('ReactNativeCameraKit', () => Example); diff --git a/ios/CameraSessionManager.swift b/ios/CameraSessionManager.swift new file mode 100644 index 0000000..d15c94c --- /dev/null +++ b/ios/CameraSessionManager.swift @@ -0,0 +1,183 @@ +// +// CameraSessionManager.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +import UIKit +import AVFoundation + +enum CameraType { + case FrontFacingCamera + case BackFacingCamera +} + +class CameraSessionManager: NSObject { + var captureDevice: AVCaptureDevice! + var previewLayer: AVCaptureVideoPreviewLayer! + var captureSession: AVCaptureSession! + var stillImageOutput: AVCaptureStillImageOutput! + var flashMode: AVCaptureFlashMode = .Auto + + override init() { + super.init() + self.captureSession = AVCaptureSession() + self.captureSession.sessionPreset = AVCaptureSessionPresetHigh + } + + convenience init(cameraType: CameraType) { + self.init() + + captureSession.beginConfiguration() + initiateCaptureSessionForCamera(cameraType) + addStillImageOutput() + addVideoPreviewLayer() + captureSession.commitConfiguration() + } + + internal func addVideoPreviewLayer() { + self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) as AVCaptureVideoPreviewLayer + self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill + } + + internal func initiateCaptureSessionForCamera(cameraType: CameraType) { + let devices = AVCaptureDevice.devices() + + for device in devices { + if (device.hasMediaType(AVMediaTypeVideo)) { + switch (cameraType) { + case .FrontFacingCamera: + if (device.position == AVCaptureDevicePosition.Front) { + self.captureDevice = device as! AVCaptureDevice + } + break + case .BackFacingCamera: + if (device.position == AVCaptureDevicePosition.Back) { + self.captureDevice = device as! AVCaptureDevice + } + break + } + } + } + + do { + let possibleCameraInput: AnyObject? = try AVCaptureDeviceInput(device: self.captureDevice) + if let cameraInput = possibleCameraInput as? AVCaptureDeviceInput { + if self.captureSession.canAddInput(cameraInput) { + self.captureSession.addInput(cameraInput) + } + } + } catch let error as NSError { + print(error) + } + } + + func assignVideoOrienationForVideoConnection(videoConnection: AVCaptureConnection) { + var newOrientation: AVCaptureVideoOrientation + switch (UIDevice.currentDevice().orientation) { + case .Portrait: + newOrientation = AVCaptureVideoOrientation.Portrait + break + case .PortraitUpsideDown: + newOrientation = AVCaptureVideoOrientation.PortraitUpsideDown + break + case .LandscapeLeft: + newOrientation = AVCaptureVideoOrientation.LandscapeRight + break + case .LandscapeRight: + newOrientation = AVCaptureVideoOrientation.LandscapeLeft + break + default: + newOrientation = AVCaptureVideoOrientation.Portrait + } + + videoConnection.videoOrientation = newOrientation + } + + func getOrientationAdaptedCaptureConnection() -> AVCaptureConnection? + { + var videoConnection: AVCaptureConnection? = nil + for connection in self.stillImageOutput.connections { + for port in connection.inputPorts! { + if (port.mediaType == AVMediaTypeVideo) { + videoConnection = connection as? AVCaptureConnection + self.assignVideoOrienationForVideoConnection(videoConnection!) + break + } + } + if (videoConnection != nil) { + break + } + } + return videoConnection + } + + internal func addStillImageOutput() { + self.stillImageOutput = AVCaptureStillImageOutput() + self.stillImageOutput.outputSettings = NSDictionary(objects: [AVVideoCodecJPEG], forKeys: [AVVideoCodecKey]) as! [NSObject : AnyObject] + self.getOrientationAdaptedCaptureConnection() + if self.captureSession.canAddOutput(self.stillImageOutput) { + self.captureSession.addOutput(self.stillImageOutput) + } + + do { + if (captureDevice.isFocusModeSupported(AVCaptureFocusMode.ContinuousAutoFocus)) { + try captureDevice.lockForConfiguration() + if captureDevice.isFlashModeSupported(self.flashMode) { + captureDevice.flashMode = self.flashMode + } + if captureDevice.isFocusModeSupported(.ContinuousAutoFocus) { + captureDevice.focusMode = AVCaptureFocusMode.ContinuousAutoFocus + } + if captureDevice.isWhiteBalanceModeSupported(.ContinuousAutoWhiteBalance) { + captureDevice.whiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance + } + captureDevice.unlockForConfiguration() + } + } catch let error as NSError { + print(error) + } + } + + internal func captureStillImage(completionHandler: ((UIImage) -> Void)!) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { + let videoConnection = self.getOrientationAdaptedCaptureConnection() + if (videoConnection != nil) { + self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: + { (imageSampleBuffer: CMSampleBuffer!, _) -> Void in + let stillImageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageSampleBuffer) + let stillImage = UIImage(data: stillImageData) + + completionHandler(stillImage!) + }) + } + } + } + + func changeFlashMode(mode: AVCaptureFlashMode) { + do { + if (captureDevice.hasFlash && captureDevice.isFlashModeSupported(mode) && captureDevice.flashMode != mode) { + try captureDevice.lockForConfiguration() + captureDevice.flashMode = mode + self.flashMode = mode + captureDevice.unlockForConfiguration() + } + } catch let error as NSError { + print(error) + } + } + + func stopSession() { + self.captureSession.stopRunning() + + for input in self.captureSession.inputs { + self.captureSession.removeInput(input as! AVCaptureInput) + } + + for output in self.captureSession.outputs { + self.captureSession.removeOutput(output as! AVCaptureOutput) + } + } +} \ No newline at end of file diff --git a/ios/CameraViewController.swift b/ios/CameraViewController.swift new file mode 100644 index 0000000..6c55afc --- /dev/null +++ b/ios/CameraViewController.swift @@ -0,0 +1,385 @@ +// +// CameraViewController.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +import UIKit +import AVFoundation +import AssetsLibrary +import Photos + +struct AspectRatio { + let widthRatio: Int + let heightRatio: Int + + init(widthRatio: Int, heightRatio: Int) { + self.widthRatio = widthRatio + self.heightRatio = heightRatio + } +} + +class CameraViewController : UIViewController, PhotoViewControllerDelegate { + var cameraViewControllerDelegate: CameraViewControllerDelegate? + + var cameraManager: CameraSessionManager! + var cameraOptions: [String: AnyObject]! + let topBarHeight: CGFloat = 50 + var topBarButtonSize: CGSize! + let bottomBarHeight: CGFloat = 115 + var flashButton: UIButton! + let flashModes = ["Auto", "On", "Off"] + var flashModeSelector: UISegmentedControl! + var ratioField = UITextField() + let aspectRatios: [String] + var aspectRatio: AspectRatio! + var ratioLayer = UIView() + var infoLabel: UITextField! + + let flashColor = UIColor(colorLiteralRed: 0.95, green: 0.76, blue: 0.2, alpha: 1) + + let assetCollectionName: String! + + init(cameraOptions: [String: AnyObject]) { + self.cameraOptions = cameraOptions + self.aspectRatios = cameraOptions["aspectRatios"] as! [String] + self.assetCollectionName = cameraOptions["collectionName"] as! String; + super.init(nibName: nil, bundle: nil) + + self.aspectRatio = self.extractRatio(aspectRatios[0]) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prefersStatusBarHidden() -> Bool { + return true + } + + override func shouldAutorotate() -> Bool { + return false + } + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + + self.setupCameraManager(.BackFacingCamera) + + let sessionQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL) + dispatch_async(sessionQueue) { () -> Void in + self.cameraManager.captureSession.startRunning() + } + + self.buildUi() + } + + private func setupCameraManager(cameraType: CameraType) { + self.cameraManager = CameraSessionManager(cameraType: cameraType) + self.cameraManager.previewLayer.frame = CGRect(x: 0, y: topBarHeight, width: self.view.frame.size.width, height: self.view.frame.size.height - (topBarHeight + bottomBarHeight)) + self.view.layer.addSublayer(self.cameraManager.previewLayer) + self.fitAspectRatio(aspectRatio) + } + + private func buildUi() { + topBarButtonSize = CGSizeMake(view.bounds.size.height * 0.04, view.bounds.size.height * 0.04) + + self.addToolbars() + self.addShutterButton() + self.addCloseButton() + self.addFlashButton() + self.addFlashModeSelector() + self.addRatioSelector() + } + + private func addToolbars() { + let topBarView = UIView() + topBarView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: topBarHeight) + topBarView.backgroundColor = UIColor.blackColor() + self.view.addSubview(topBarView) + + let bottomBarView = UIView() + bottomBarView.frame = CGRect(x: 0, y: self.view.frame.size.height - bottomBarHeight, width: self.view.frame.size.width, height: bottomBarHeight) + bottomBarView.backgroundColor = UIColor.blackColor() + self.view.addSubview(bottomBarView) + } + + private func addShutterButton() { + let shutterButtonSize = CGSizeMake(self.view.bounds.size.width * 0.23, self.view.bounds.size.width * 0.23) + + let image = UIImage(named: "ShutterIcon") as UIImage? + let button = UIButton(type: UIButtonType.Custom) as UIButton + button.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: shutterButtonSize) + button.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height - shutterButtonSize.height / 2 - 5) + button.setImage(image, forState: .Normal) + + button.addTarget(self, action: "onTakePhoto:", forControlEvents: UIControlEvents.TouchUpInside) + + self.view.addSubview(button) + } + + private func addCloseButton() { + let image = UIImage(named: "CloseIcon") as UIImage? + let closeButton = UIButton(type: UIButtonType.Custom) as UIButton + closeButton.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: topBarButtonSize) + closeButton.center = CGPointMake(topBarButtonSize.width / 2, topBarHeight / 2) + closeButton.setImage(image, forState: .Normal) + + closeButton.addTarget(self, action: "onClose:", forControlEvents: UIControlEvents.TouchUpInside) + + self.view.addSubview(closeButton) + } + + func addFlashButton() { + let image = UIImage(named: "FlashAutoIcon") as UIImage? + flashButton = UIButton(type: UIButtonType.Custom) as UIButton + flashButton.frame = CGRect(origin: CGPoint(x: self.view.bounds.size.width - topBarButtonSize.width, y: 0), size: topBarButtonSize) + flashButton.center = CGPointMake(self.view.bounds.size.width - topBarButtonSize.width / 2, topBarHeight / 2) + flashButton.setImage(image, forState: .Normal) + + flashButton.addTarget(self, action: "onFlashChange:", forControlEvents: UIControlEvents.TouchUpInside) + + self.view.addSubview(flashButton) + } + + func addFlashModeSelector() { + let controlWidth = 0.6 * self.view.bounds.size.width + flashModeSelector = UISegmentedControl(items: flashModes) + flashModeSelector.selectedSegmentIndex = 0 + flashModeSelector.frame = CGRectMake((self.view.bounds.size.width - controlWidth) / 2, 0, controlWidth, topBarHeight) + flashModeSelector.backgroundColor = UIColor.clearColor() + flashModeSelector.tintColor = UIColor.clearColor() + + flashModeSelector.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.whiteColor()], forState: UIControlState.Normal) + flashModeSelector.setTitleTextAttributes([NSForegroundColorAttributeName: flashColor], forState: UIControlState.Selected) + + flashModeSelector.addTarget(self, action: "changeFlashMode:", forControlEvents: .ValueChanged) + } + + func addRatioSelector() { + let ratioPicker = UIPickerView() + ratioPicker.showsSelectionIndicator = true + ratioPicker.delegate = self + ratioPicker.dataSource = self + + let toolBar = UIToolbar() + toolBar.barStyle = UIBarStyle.Default + toolBar.tintColor = UIColor.blackColor() + toolBar.translucent = true + toolBar.sizeToFit() + let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "onRatioSelected:") + toolBar.setItems([doneButton], animated: false) + toolBar.userInteractionEnabled = true + + let fieldHeight: CGFloat = 40 + + ratioField.tintColor = UIColor.clearColor() + ratioField.inputView = ratioPicker + ratioField.inputAccessoryView = toolBar + ratioField.text = aspectRatios[0] + ratioField.frame = CGRectMake(self.view.frame.size.width * 0.85, self.view.frame.size.height - bottomBarHeight, self.view.frame.size.width * 0.15, fieldHeight) + ratioField.textAlignment = NSTextAlignment.Right + ratioField.contentVerticalAlignment = UIControlContentVerticalAlignment.Center + ratioField.textColor = flashColor + self.view.addSubview(ratioField) + self.view.addSubview(ratioLayer) + + infoLabel = UITextField() + infoLabel.text = cameraOptions["aspectRatioInfoMessage"] as! String + infoLabel.adjustsFontSizeToFitWidth = true + infoLabel.textColor = UIColor.whiteColor() + infoLabel.textAlignment = NSTextAlignment.Left + infoLabel.frame = CGRectMake(0, self.view.frame.size.height - bottomBarHeight, self.view.frame.size.width * 0.75, fieldHeight) + infoLabel.inputView = ratioPicker + infoLabel.inputAccessoryView = toolBar + self.view.addSubview(infoLabel) + } + + private func fitAspectRatio(aspectRatio: AspectRatio) { + let previewLayerExcess = CropHelper.cropRectangleToFitRatio(self.cameraManager.previewLayer.frame.width, originalRectangleHeight: self.cameraManager.previewLayer.frame.height, widthRatio: aspectRatio.widthRatio, heightRatio: aspectRatio.heightRatio) + + let backgroundColor = UIColor(white: 0, alpha: 0.5) + + self.ratioLayer.removeFromSuperview() + self.ratioLayer = UIView(frame: CGRect(origin: self.cameraManager.previewLayer.frame.origin, size: self.cameraManager.previewLayer.frame.size)) + self.view.addSubview(self.ratioLayer) + + if (previewLayerExcess.verticalExcess != 0.0) { + let topExcess = UIView() + topExcess.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: self.cameraManager.previewLayer.frame.width, height: previewLayerExcess.verticalExcess / 2)) + topExcess.backgroundColor = backgroundColor + self.ratioLayer.addSubview(topExcess) + + let bottomExcess = UIView() + bottomExcess.frame = CGRect(x: self.cameraManager.previewLayer.frame.origin.x, y: self.cameraManager.previewLayer.frame.height - previewLayerExcess.verticalExcess / 2, width: self.cameraManager.previewLayer.frame.width, height: previewLayerExcess.verticalExcess / 2) + bottomExcess.backgroundColor = backgroundColor + self.ratioLayer.addSubview(bottomExcess) + } else { + let leftExcess = UIView() + leftExcess.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: previewLayerExcess.horizontalExcess / 2, height: self.cameraManager.previewLayer.frame.height)) + leftExcess.backgroundColor = backgroundColor + self.ratioLayer.addSubview(leftExcess) + + let rightExcess = UIView() + rightExcess.frame = CGRect(x: self.cameraManager.previewLayer.frame.origin.x + self.cameraManager.previewLayer.frame.width - previewLayerExcess.horizontalExcess / 2, y: 0, width: previewLayerExcess.horizontalExcess / 2, height: self.cameraManager.previewLayer.frame.height) + rightExcess.backgroundColor = backgroundColor + self.ratioLayer.addSubview(rightExcess) + } + } + + func onFlashChange(sender: UIButton) { + sender.selected = !sender.selected + if sender.selected { + flashButton.setImage(UIImage(named: "FlashAutoIcon") as UIImage?, forState: .Normal) + self.view.addSubview(flashModeSelector) + } else { + flashModeSelector.removeFromSuperview() + setFlashIcon() + } + } + + func onRatioSelected(sender: UIButton) { + self.ratioField.resignFirstResponder() + self.infoLabel.resignFirstResponder() + } + + func changeFlashMode(_: UISegmentedControl) { + setFlashIcon() + flashButton.selected = false + flashModeSelector.removeFromSuperview() + } + + private func setFlashIcon() { + switch flashModeSelector.selectedSegmentIndex { + case 1: + cameraManager.changeFlashMode(.On) + flashButton.setImage(UIImage(named: "FlashOnIcon") as UIImage?, forState: .Normal) + break + case 2: + cameraManager.changeFlashMode(.Off) + flashButton.setImage(UIImage(named: "FlashOffIcon") as UIImage?, forState: .Normal) + break + default: + cameraManager.changeFlashMode(.Auto) + flashButton.setImage(UIImage(named: "FlashAutoIcon") as UIImage?, forState: .Normal) + break + } + } + + func onTakePhoto(sender: UIButton) { + self.cameraManager.captureStillImage({ (image: UIImage) -> Void in + let croppedImage = self.cropImage(image) + self.showPhotoViewController(croppedImage) + }) + } + + func onClose(sender: UIButton) { + self.cameraManager.stopSession() + //dismissViewControllerAnimated(true, completion: nil) + if let delegate = self.cameraViewControllerDelegate { + delegate.cameraViewControllerDidCancel(self) + } + } + + func showPhotoViewController(image: UIImage) { + let photoViewController = PhotoViewController(image: image) + photoViewController.delegate = self + photoViewController.view.bounds = self.view.bounds + self.addChildViewController(photoViewController) + self.view.addSubview(photoViewController.view) + photoViewController.didMoveToParentViewController(self) + } + + func hidePhotoViewController(controller: PhotoViewController) { + controller.willMoveToParentViewController(nil) + controller.view.removeFromSuperview() + controller.removeFromParentViewController() + } + + //PhotoViewControllerDelegate + + func retakePhoto(controller: PhotoViewController) { + self.hidePhotoViewController(controller) + } + + func usePhoto(controller: PhotoViewController, photo: UIImage) { + dismissViewControllerAnimated(true, completion: nil) + let imageData = UIImageJPEGRepresentation(photo, 1.0) + let base64 = imageData!.base64EncodedStringWithOptions([]) + + var assetCollection: PHAssetCollection? + var assetCollectionPlaceholder: PHObjectPlaceholder? + + let fetchOptions = PHFetchOptions() + fetchOptions.predicate = NSPredicate(format: "title = %@", self.assetCollectionName) + let collection : PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions) + if let _: AnyObject = collection.firstObject { + assetCollection = collection.firstObject as? PHAssetCollection + savePhoto(base64, photo: photo, assetCollection: assetCollection!) + } else { + PHPhotoLibrary.sharedPhotoLibrary().performChanges({ + let createAlbumRequest : PHAssetCollectionChangeRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle(self.assetCollectionName) + assetCollectionPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection + }, completionHandler: { success, error in + if (success) { + let collectionFetchResult = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([assetCollectionPlaceholder!.localIdentifier], options: nil) + assetCollection = collectionFetchResult.firstObject as? PHAssetCollection + self.savePhoto(base64, photo: photo, assetCollection: assetCollection!) + } + }) + } + } + + private func savePhoto(imageData: String, photo: UIImage, assetCollection: PHAssetCollection) { + PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in + let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(photo) + let assetPlaceholder = assetRequest.placeholderForCreatedAsset + let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: assetCollection) + albumChangeRequest!.addAssets([assetPlaceholder!]) + }, completionHandler: { (success, error) -> Void in + self.cameraManager.stopSession() + if let delegate = self.cameraViewControllerDelegate { + if success { + delegate.imageHasBeenTaken(self, imageData: imageData) + } else { + delegate.onError(self, error: (error?.localizedDescription)!) + } + } + }) + } + + + func cropImage(image: UIImage) -> UIImage { + let barPart: CGFloat = (topBarHeight + bottomBarHeight) / self.view.bounds.size.height + return CropHelper.cropImage(image, widthRatio: aspectRatio.widthRatio, heightRatio: aspectRatio.heightRatio, verticalPartToCrop: barPart) + } + + func extractRatio(ratioString: String) -> AspectRatio { + let ratios = ratioString.characters.split{$0 == ":"}.map(String.init) + return AspectRatio(widthRatio: Int(ratios[0])!, heightRatio: Int(ratios[1])!) + } +} + +extension CameraViewController: UIPickerViewDataSource { + func numberOfComponentsInPickerView(colorPicker: UIPickerView) -> Int { + return 1 + } + + func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return aspectRatios.count + } +} + +extension CameraViewController: UIPickerViewDelegate { + func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + return aspectRatios[row] + } + + func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + ratioField.text = aspectRatios[row] + self.aspectRatio = self.extractRatio(aspectRatios[row]) + self.fitAspectRatio(self.aspectRatio) + } +} diff --git a/ios/CameraViewControllerDelegate.swift b/ios/CameraViewControllerDelegate.swift new file mode 100644 index 0000000..4d309e0 --- /dev/null +++ b/ios/CameraViewControllerDelegate.swift @@ -0,0 +1,13 @@ +// +// CameraViewControllerDelegate.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +protocol CameraViewControllerDelegate : NSObjectProtocol { + func imageHasBeenTaken(controller: CameraViewController, imageData: String) + func cameraViewControllerDidCancel(controller: CameraViewController) + func onError(controller: CameraViewController, error: String) +} diff --git a/ios/CropHelper.swift b/ios/CropHelper.swift new file mode 100644 index 0000000..0a9629e --- /dev/null +++ b/ios/CropHelper.swift @@ -0,0 +1,58 @@ +// +// CropHelper.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + + +import UIKit + +struct CropInfo { + var verticalExcess: CGFloat + var horizontalExcess: CGFloat + + init(verticalExcess: CGFloat, horizontalExcess: CGFloat) { + self.verticalExcess = verticalExcess + self.horizontalExcess = horizontalExcess + } +} + +class CropHelper: NSObject { + static func cropImage(image: UIImage, widthRatio: Int, heightRatio: Int, verticalPartToCrop: CGFloat = 0) -> UIImage { + let contextImage: UIImage = UIImage(CGImage: image.CGImage!) + let contextSize: CGSize = contextImage.size + + let offset = verticalPartToCrop * contextSize.width + let cropInfo = cropRectangleToFitRatio(contextSize.width - offset, originalRectangleHeight: contextSize.height, widthRatio: heightRatio, heightRatio: widthRatio) + + let rect = CGRectMake(offset / 2 + cropInfo.horizontalExcess / 2, cropInfo.verticalExcess / 2, contextSize.width - (offset + cropInfo.horizontalExcess), contextSize.height - cropInfo.verticalExcess) + let imageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect) + let newImage = UIImage(CGImage: imageRef!, scale: image.scale, orientation: image.imageOrientation) + + return newImage + } + + static func cropRectangleToFitRatio(originalRectangleWidth: CGFloat, originalRectangleHeight: CGFloat, widthRatio: Int, heightRatio: Int) -> CropInfo { + var newHeight = originalRectangleHeight + var newWidth = originalRectangleWidth + + if (widthRatio > heightRatio) { + newHeight = originalRectangleWidth * CGFloat(heightRatio) / CGFloat(widthRatio) + } else { + if (widthRatio < heightRatio) { + newWidth = originalRectangleHeight * CGFloat(widthRatio) / CGFloat(heightRatio) + } else { + if (originalRectangleWidth > originalRectangleHeight) { + newWidth = originalRectangleHeight + } else { + newHeight = originalRectangleWidth + } + } + } + + return CropInfo(verticalExcess: originalRectangleHeight - newHeight, horizontalExcess: originalRectangleWidth - newWidth) + } +} + diff --git a/ios/PhotoViewController.swift b/ios/PhotoViewController.swift new file mode 100644 index 0000000..8e75e68 --- /dev/null +++ b/ios/PhotoViewController.swift @@ -0,0 +1,78 @@ +// +// PhotoViewController.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +class PhotoViewController: UIViewController { + let image: UIImage + var delegate: PhotoViewControllerDelegate? + + let topBarHeight: CGFloat = 50 + let bottomBarHeight: CGFloat = 50 + let buttonMargin: CGFloat = 10 + + init(image: UIImage) { + self.image = image + super.init(nibName: nil, bundle: nil) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prefersStatusBarHidden() -> Bool { + return true + } + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + + var imageViewWidth, imageViewHeight: CGFloat + let imageView = UIImageView(image: self.image) + if (image.size.width >= image.size.height) { + imageViewWidth = self.view.frame.size.width + imageViewHeight = imageViewWidth * image.size.height / image.size.width + } else { + imageViewHeight = self.view.frame.size.height - (topBarHeight + bottomBarHeight) + imageViewWidth = imageViewHeight * image.size.width / image.size.height + } + imageView.frame = CGRectMake(self.view.frame.size.width / 2 - imageViewWidth / 2, self.view.frame.size.height / 2 - imageViewHeight / 2, imageViewWidth, imageViewHeight) + self.view.backgroundColor = UIColor.blackColor() + self.view.addSubview(imageView) + + let retakePhoto = "Retake" + let retakeButton = UIButton(type: UIButtonType.Custom) as UIButton + retakeButton.setTitle(retakePhoto, forState: .Normal) + retakeButton.setTitleColor(UIColor.whiteColor(), forState: .Normal) + let retakeLabelSize = retakePhoto.sizeWithAttributes([NSFontAttributeName: retakeButton.titleLabel!.font]) + retakeButton.frame = CGRect(origin: CGPoint(x: 0, y: self.view.frame.size.height - bottomBarHeight), size: CGSize(width: retakeLabelSize.width + 2 * buttonMargin, height: bottomBarHeight)) + retakeButton.addTarget(self, action: "onRetakePhoto:", forControlEvents: UIControlEvents.TouchUpInside) + self.view.addSubview(retakeButton) + + let usePhoto = "Use Photo" + let useButton = UIButton(type: UIButtonType.Custom) as UIButton + useButton.setTitle(usePhoto, forState: .Normal) + useButton.setTitleColor(UIColor.whiteColor(), forState: .Normal) + let useLabelSize = usePhoto.sizeWithAttributes([NSFontAttributeName: useButton.titleLabel!.font]) + let useButtonWidth = useLabelSize.width + 2 * buttonMargin + useButton.frame = CGRect(origin: CGPoint(x: self.view.frame.size.width - useButtonWidth, y: self.view.frame.size.height - bottomBarHeight), size: CGSize(width: useButtonWidth, height: bottomBarHeight)) + useButton.addTarget(self, action: "onUsePhoto:", forControlEvents: UIControlEvents.TouchUpInside) + self.view.addSubview(useButton) + } + + func onRetakePhoto(sender: UIButton) { + if let delegate = self.delegate { + delegate.retakePhoto(self) + } + } + + func onUsePhoto(sender: UIButton) { + if let delegate = self.delegate { + delegate.usePhoto(self, photo: image) + } + } +} + diff --git a/ios/PhotoViewControllerDelegate.swift b/ios/PhotoViewControllerDelegate.swift new file mode 100644 index 0000000..acc4ff8 --- /dev/null +++ b/ios/PhotoViewControllerDelegate.swift @@ -0,0 +1,12 @@ +// +// PhotoViewControllerDelegate.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +protocol PhotoViewControllerDelegate : NSObjectProtocol { + func retakePhoto(controller: PhotoViewController) + func usePhoto(controller: PhotoViewController, photo: UIImage) +} diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..06a847d --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,13 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '8.0' +# Uncomment this line if you're using Swift +use_frameworks! + +target 'ReactNativeCameraKit' do +pod "ImagePickerSheetController" +end + +target 'ReactNativeCameraKitTests' do + +end + diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..e6e876b --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,10 @@ +PODS: + - ImagePickerSheetController (0.9.1) + +DEPENDENCIES: + - ImagePickerSheetController + +SPEC CHECKSUMS: + ImagePickerSheetController: 3c58c9fee6dcf36485222358a021f6b734f997ba + +COCOAPODS: 0.39.0 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/AnimationController.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/AnimationController.swift new file mode 100644 index 0000000..915a8fb --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/AnimationController.swift @@ -0,0 +1,80 @@ +// +// AnimationController.swift +// ImagePickerSheet +// +// Created by Laurin Brandner on 25/05/15. +// Copyright (c) 2015 Laurin Brandner. All rights reserved. +// + +import UIKit + +class AnimationController: NSObject { + + let imagePickerSheetController: ImagePickerSheetController + let presenting: Bool + + // MARK: - Initialization + + init(imagePickerSheetController: ImagePickerSheetController, presenting: Bool) { + self.imagePickerSheetController = imagePickerSheetController + self.presenting = presenting + } + + // MARK: - Animation + + private func animatePresentation(context: UIViewControllerContextTransitioning) { + guard let containerView = context.containerView() else { + return + } + + containerView.addSubview(imagePickerSheetController.view) + + let sheetOriginY = imagePickerSheetController.sheetCollectionView.frame.origin.y + imagePickerSheetController.sheetCollectionView.frame.origin.y = containerView.bounds.maxY + imagePickerSheetController.backgroundView.alpha = 0 + + UIView.animateWithDuration(transitionDuration(context), delay: 0, options: .CurveEaseOut, animations: { () -> Void in + self.imagePickerSheetController.sheetCollectionView.frame.origin.y = sheetOriginY + self.imagePickerSheetController.backgroundView.alpha = 1 + }, completion: { _ in + context.completeTransition(true) + }) + } + + private func animateDismissal(context: UIViewControllerContextTransitioning) { + guard let containerView = context.containerView() else { + return + } + + UIView.animateWithDuration(transitionDuration(context), delay: 0, options: .CurveEaseIn, animations: { () -> Void in + self.imagePickerSheetController.sheetCollectionView.frame.origin.y = containerView.bounds.maxY + self.imagePickerSheetController.backgroundView.alpha = 0 + }, completion: { _ in + self.imagePickerSheetController.view.removeFromSuperview() + context.completeTransition(true) + }) + } + +} + +// MARK: - UIViewControllerAnimatedTransitioning +extension AnimationController: UIViewControllerAnimatedTransitioning { + + func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { + guard #available(iOS 9, *) else { + return 0.3 + } + + return 0.25 + } + + func animateTransition(transitionContext: UIViewControllerContextTransitioning) { + if presenting { + animatePresentation(transitionContext) + } + else { + animateDismissal(transitionContext) + } + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerAction.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerAction.swift new file mode 100644 index 0000000..7469a86 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerAction.swift @@ -0,0 +1,75 @@ +// +// ImagePickerAction.swift +// ImagePickerSheet +// +// Created by Laurin Brandner on 24/05/15. +// Copyright (c) 2015 Laurin Brandner. All rights reserved. +// + +import Foundation + +public enum ImagePickerActionStyle { + case Default + case Cancel +} + +public class ImagePickerAction { + + public typealias Title = Int -> String + public typealias Handler = (ImagePickerAction) -> () + public typealias SecondaryHandler = (ImagePickerAction, Int) -> () + + /// The title of the action's button. + public let title: String + + /// The title of the action's button when more than one image is selected. + public let secondaryTitle: Title + + /// The style of the action. This is used to call a cancel handler when dismissing the controller by tapping the background. + public let style: ImagePickerActionStyle + + let handler: Handler + let secondaryHandler: SecondaryHandler + + /// Initializes a new ImagePickerAction. The secondary title and handler are used when at least 1 image has been selected. + /// Secondary title defaults to title if not specified. + /// Secondary handler defaults to handler if not specified. + public convenience init(title: String, secondaryTitle: String? = nil, style: ImagePickerActionStyle = .Default, handler: Handler, secondaryHandler: SecondaryHandler? = nil) { + self.init(title: title, secondaryTitle: secondaryTitle.map { string in { _ in string }}, style: style, handler: handler, secondaryHandler: secondaryHandler) + } + + /// Initializes a new ImagePickerAction. The secondary title and handler are used when at least 1 image has been selected. + /// Secondary title defaults to title if not specified. Use the closure to format a title according to the selection. + /// Secondary handler defaults to handler if not specified + public init(title: String, secondaryTitle: Title?, style: ImagePickerActionStyle = .Default, handler: Handler, var secondaryHandler: SecondaryHandler? = nil) { + if secondaryHandler == nil { + secondaryHandler = { action, _ in + handler(action) + } + } + + self.title = title + self.secondaryTitle = secondaryTitle ?? { _ in title } + self.style = style + self.handler = handler + self.secondaryHandler = secondaryHandler! + } + + func handle(numberOfImages: Int = 0) { + if numberOfImages > 0 { + secondaryHandler(self, numberOfImages) + } + else { + handler(self) + } + } + +} + +func ?? (left: ImagePickerAction.Title?, right: ImagePickerAction.Title) -> ImagePickerAction.Title { + if let left = left { + return left + } + + return right +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController.swift new file mode 100644 index 0000000..5009e74 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController.swift @@ -0,0 +1,482 @@ +// +// ImagePickerController.swift +// ImagePickerSheet +// +// Created by Laurin Brandner on 24/05/15. +// Copyright (c) 2015 Laurin Brandner. All rights reserved. +// + +import Foundation +import Photos + +private let previewCollectionViewInset: CGFloat = 5 + +/// The media type an instance of ImagePickerSheetController can display +public enum ImagePickerMediaType { + case Image + case Video + case ImageAndVideo +} + +@available(iOS 8.0, *) +public class ImagePickerSheetController: UIViewController { + + private lazy var sheetController: SheetController = { + let controller = SheetController(previewCollectionView: self.previewCollectionView) + controller.actionHandlingCallback = { [weak self] in + self?.dismissViewControllerAnimated(true, completion: nil) + } + + return controller + }() + + var sheetCollectionView: UICollectionView { + return sheetController.sheetCollectionView + } + + private(set) lazy var previewCollectionView: PreviewCollectionView = { + let collectionView = PreviewCollectionView() + collectionView.accessibilityIdentifier = "ImagePickerSheetPreview" + collectionView.backgroundColor = .clearColor() + collectionView.allowsMultipleSelection = true + collectionView.imagePreviewLayout.sectionInset = UIEdgeInsetsMake(previewCollectionViewInset, previewCollectionViewInset, previewCollectionViewInset, previewCollectionViewInset) + collectionView.imagePreviewLayout.showsSupplementaryViews = false + collectionView.dataSource = self + collectionView.delegate = self + collectionView.showsHorizontalScrollIndicator = false + collectionView.alwaysBounceHorizontal = true + collectionView.registerClass(PreviewCollectionViewCell.self, forCellWithReuseIdentifier: NSStringFromClass(PreviewCollectionViewCell.self)) + collectionView.registerClass(PreviewSupplementaryView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: NSStringFromClass(PreviewSupplementaryView.self)) + + return collectionView + }() + + private var supplementaryViews = [Int: PreviewSupplementaryView]() + + lazy var backgroundView: UIView = { + let view = UIView() + view.accessibilityIdentifier = "ImagePickerSheetBackground" + view.backgroundColor = UIColor(white: 0.0, alpha: 0.3961) + view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "cancel")) + + return view + }() + + /// All the actions. The first action is shown at the top. + public var actions: [ImagePickerAction] { + return sheetController.actions + } + + /// Maximum selection of images. + public var maximumSelection: Int? + + private var selectedImageIndices = [Int]() { + didSet { + sheetController.numberOfSelectedImages = selectedImageIndices.count + } + } + + /// The selected image assets + public var selectedImageAssets: [PHAsset] { + return selectedImageIndices.map { self.assets[$0] } + } + + /// The media type of the displayed assets + public let mediaType: ImagePickerMediaType + + private var assets = [PHAsset]() + + private lazy var requestOptions: PHImageRequestOptions = { + let options = PHImageRequestOptions() + options.deliveryMode = .HighQualityFormat + options.resizeMode = .Fast + + return options + }() + + private let imageManager = PHCachingImageManager() + + /// Whether the image preview has been elarged. This is the case when at least once + /// image has been selected. + public private(set) var enlargedPreviews = false + + private let minimumPreviewHeight: CGFloat = 129 + private var maximumPreviewHeight: CGFloat = 129 + + private var previewCheckmarkInset: CGFloat { + guard #available(iOS 9, *) else { + return 3.5 + } + + return 12.5 + } + + // MARK: - Initialization + + public init(mediaType: ImagePickerMediaType) { + self.mediaType = mediaType + super.init(nibName: nil, bundle: nil) + initialize() + } + + public required init?(coder aDecoder: NSCoder) { + self.mediaType = .ImageAndVideo + super.init(coder: aDecoder) + initialize() + } + + private func initialize() { + modalPresentationStyle = .Custom + transitioningDelegate = self + + NSNotificationCenter.defaultCenter().addObserver(self, selector: "cancel", name: UIApplicationDidEnterBackgroundNotification, object: nil) + } + + deinit { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + // MARK: - View Lifecycle + + override public func loadView() { + super.loadView() + + view.addSubview(backgroundView) + view.addSubview(sheetCollectionView) + } + + public override func viewWillAppear(animated: Bool) { + super.viewWillAppear(animated) + + preferredContentSize = CGSize(width: 400, height: view.frame.height) + + if PHPhotoLibrary.authorizationStatus() == .Authorized { + prepareAssets() + } + } + + public override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + + if PHPhotoLibrary.authorizationStatus() == .NotDetermined { + PHPhotoLibrary.requestAuthorization() { status in + if status == .Authorized { + dispatch_async(dispatch_get_main_queue()) { + self.prepareAssets() + self.previewCollectionView.reloadData() + self.sheetCollectionView.reloadData() + self.view.setNeedsLayout() + + // Explicitely disable animations so it wouldn't animate either + // if it was in a popover + CATransaction.begin() + CATransaction.setDisableActions(true) + self.view.layoutIfNeeded() + CATransaction.commit() + } + } + } + } + } + + // MARK: - Actions + + /// Adds an new action. + /// If the passed action is of type Cancel, any pre-existing Cancel actions will be removed. + /// Always arranges the actions so that the Cancel action appears at the bottom. + public func addAction(action: ImagePickerAction) { + sheetController.addAction(action) + view.setNeedsLayout() + } + + @objc private func cancel() { + sheetController.handleCancelAction() + } + + // MARK: - Images + + private func sizeForAsset(asset: PHAsset, scale: CGFloat = 1) -> CGSize { + let proportion = CGFloat(asset.pixelWidth)/CGFloat(asset.pixelHeight) + + let imageHeight = maximumPreviewHeight - 2 * previewCollectionViewInset + let imageWidth = floor(proportion * imageHeight) + + return CGSize(width: imageWidth * scale, height: imageHeight * scale) + } + + private func prepareAssets() { + fetchAssets() + reloadMaximumPreviewHeight() + reloadCurrentPreviewHeight(invalidateLayout: false) + + // Filter out the assets that are too thin. This can't be done before becuase + // we don't know how tall the images should be + let minImageWidth = 2 * previewCheckmarkInset + (PreviewSupplementaryView.checkmarkImage?.size.width ?? 0) + assets = assets.filter { asset in + let size = sizeForAsset(asset) + return size.width >= minImageWidth + } + } + + private func fetchAssets() { + let options = PHFetchOptions() + options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] + + switch mediaType { + case .Image: + options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue) + case .Video: + options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Video.rawValue) + case .ImageAndVideo: + options.predicate = NSPredicate(format: "mediaType = %d OR mediaType = %d", PHAssetMediaType.Image.rawValue, PHAssetMediaType.Video.rawValue) + } + + let fetchLimit = 50 + if #available(iOS 9, *) { + options.fetchLimit = fetchLimit + } + + let result = PHAsset.fetchAssetsWithOptions(options) + let requestOptions = PHImageRequestOptions() + requestOptions.synchronous = true + requestOptions.deliveryMode = .FastFormat + + result.enumerateObjectsUsingBlock { asset, _, stop in + defer { + if self.assets.count > fetchLimit { + stop.initialize(true) + } + } + + if let asset = asset as? PHAsset { + self.imageManager.requestImageDataForAsset(asset, options: requestOptions) { data, _, _, info in + if data != nil { + self.assets.append(asset) + } + } + } + } + } + + private func requestImageForAsset(asset: PHAsset, completion: (image: UIImage?) -> ()) { + let targetSize = sizeForAsset(asset, scale: UIScreen.mainScreen().scale) + requestOptions.synchronous = true + + // Workaround because PHImageManager.requestImageForAsset doesn't work for burst images + if asset.representsBurst { + imageManager.requestImageDataForAsset(asset, options: requestOptions) { data, _, _, _ in + let image = data.flatMap { UIImage(data: $0) } + completion(image: image) + } + } + else { + imageManager.requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: requestOptions) { image, _ in + completion(image: image) + } + } + } + + private func prefetchImagesForAsset(asset: PHAsset) { + let targetSize = sizeForAsset(asset, scale: UIScreen.mainScreen().scale) + imageManager.startCachingImagesForAssets([asset], targetSize: targetSize, contentMode: .AspectFill, options: requestOptions) + } + + // MARK: - Layout + + public override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + backgroundView.frame = view.bounds + + reloadMaximumPreviewHeight() + reloadCurrentPreviewHeight(invalidateLayout: true) + + let sheetHeight = sheetController.preferredSheetHeight + let sheetSize = CGSize(width: view.bounds.width, height: sheetHeight) + + // This particular order is necessary so that the sheet is layed out + // correctly with and without an enclosing popover + preferredContentSize = sheetSize + sheetCollectionView.frame = CGRect(origin: CGPoint(x: view.bounds.minX, y: view.bounds.maxY-sheetHeight), size: sheetSize) + } + + private func reloadCurrentPreviewHeight(invalidateLayout invalidate: Bool) { + if assets.count <= 0 { + sheetController.setPreviewHeight(0, invalidateLayout: invalidate) + } + else if assets.count > 0 && enlargedPreviews { + sheetController.setPreviewHeight(maximumPreviewHeight, invalidateLayout: invalidate) + } + else { + sheetController.setPreviewHeight(minimumPreviewHeight, invalidateLayout: invalidate) + } + } + + private func reloadMaximumPreviewHeight() { + let maxHeight: CGFloat = 400 + let maxImageWidth = sheetController.preferredSheetWidth - 2 * previewCollectionViewInset + + let assetRatios = assets.map { CGSize(width: max($0.pixelHeight, $0.pixelWidth), height: min($0.pixelHeight, $0.pixelWidth)) } + .map { $0.height / $0.width } + + let assetHeights = assetRatios.map { $0 * maxImageWidth } + .filter { $0 < maxImageWidth && $0 < maxHeight } // Make sure the preview isn't too high eg for squares + .sort(>) + let assetHeight = ceil(assetHeights.first ?? 0) + + // Just a sanity check, to make sure this doesn't exceed 400 points + let scaledHeight = max(min(assetHeight, maxHeight), 200) + maximumPreviewHeight = scaledHeight + 2 * previewCollectionViewInset + } + + // MARK: - + + func enlargePreviewsByCenteringToIndexPath(indexPath: NSIndexPath?, completion: (Bool -> ())?) { + enlargedPreviews = true + previewCollectionView.imagePreviewLayout.invalidationCenteredIndexPath = indexPath + reloadCurrentPreviewHeight(invalidateLayout: false) + + view.setNeedsLayout() + + let animationDuration: NSTimeInterval + if #available(iOS 9, *) { + animationDuration = 0.2 + } + else { + animationDuration = 0.3 + } + + UIView.animateWithDuration(animationDuration, animations: { + self.sheetCollectionView.reloadSections(NSIndexSet(index: 0)) + self.view.layoutIfNeeded() + }, completion: completion) + } + +} + +// MARK: - UICollectionViewDataSource + +extension ImagePickerSheetController: UICollectionViewDataSource { + + public func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { + return assets.count + } + + public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return 1 + } + + public func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCellWithReuseIdentifier(NSStringFromClass(PreviewCollectionViewCell.self), forIndexPath: indexPath) as! PreviewCollectionViewCell + + let asset = assets[indexPath.section] + cell.videoIndicatorView.hidden = asset.mediaType != .Video + + requestImageForAsset(asset) { image in + cell.imageView.image = image + } + + cell.selected = selectedImageIndices.contains(indexPath.section) + + return cell + } + + public func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: + NSIndexPath) -> UICollectionReusableView { + let view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: NSStringFromClass(PreviewSupplementaryView.self), forIndexPath: indexPath) as! PreviewSupplementaryView + view.userInteractionEnabled = false + view.buttonInset = UIEdgeInsetsMake(0.0, previewCheckmarkInset, previewCheckmarkInset, 0.0) + view.selected = selectedImageIndices.contains(indexPath.section) + + supplementaryViews[indexPath.section] = view + + return view + } + +} + +// MARK: - UICollectionViewDelegate + +extension ImagePickerSheetController: UICollectionViewDelegate { + + public func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + if let maximumSelection = maximumSelection { + if selectedImageIndices.count >= maximumSelection, + let previousItemIndex = selectedImageIndices.first { + supplementaryViews[previousItemIndex]?.selected = false + selectedImageIndices.removeAtIndex(0) + } + } + + // Just to make sure the image is only selected once + selectedImageIndices = selectedImageIndices.filter { $0 != indexPath.section } + selectedImageIndices.append(indexPath.section) + + if !enlargedPreviews { + enlargePreviewsByCenteringToIndexPath(indexPath) { _ in + self.sheetController.reloadActionItems() + self.previewCollectionView.imagePreviewLayout.showsSupplementaryViews = true + } + } + else { + // scrollToItemAtIndexPath doesn't work reliably + if let cell = collectionView.cellForItemAtIndexPath(indexPath) { + var contentOffset = CGPointMake(cell.frame.midX - collectionView.frame.width / 2.0, 0.0) + contentOffset.x = max(contentOffset.x, -collectionView.contentInset.left) + contentOffset.x = min(contentOffset.x, collectionView.contentSize.width - collectionView.frame.width + collectionView.contentInset.right) + + collectionView.setContentOffset(contentOffset, animated: true) + } + + sheetController.reloadActionItems() + } + + supplementaryViews[indexPath.section]?.selected = true + } + + public func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) { + if let index = selectedImageIndices.indexOf(indexPath.section) { + selectedImageIndices.removeAtIndex(index) + sheetController.reloadActionItems() + } + + supplementaryViews[indexPath.section]?.selected = false + } + +} + +// MARK: - UICollectionViewDelegateFlowLayout + +extension ImagePickerSheetController: UICollectionViewDelegateFlowLayout { + + public func collectionView(collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { + let asset = assets[indexPath.section] + let size = sizeForAsset(asset) + + // Scale down to the current preview height, sizeForAsset returns the original size + let currentImagePreviewHeight = sheetController.previewHeight - 2 * previewCollectionViewInset + let scale = currentImagePreviewHeight / size.height + + return CGSize(width: size.width * scale, height: currentImagePreviewHeight) + } + + public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + let checkmarkWidth = PreviewSupplementaryView.checkmarkImage?.size.width ?? 0 + return CGSizeMake(checkmarkWidth + 2 * previewCheckmarkInset, sheetController.previewHeight - 2 * previewCollectionViewInset) + } + +} + +// MARK: - UIViewControllerTransitioningDelegate + +extension ImagePickerSheetController: UIViewControllerTransitioningDelegate { + + public func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { + return AnimationController(imagePickerSheetController: self, presenting: true) + } + + public func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { + return AnimationController(imagePickerSheetController: self, presenting: false) + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/Contents.json b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/Contents.json b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/Contents.json new file mode 100644 index 0000000..673f028 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "PreviewCollectionViewCell-video.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "PreviewCollectionViewCell-video@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "PreviewCollectionViewCell-video@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video.png new file mode 100644 index 0000000000000000000000000000000000000000..26332b8bdbde4d3b419a657a72fdea9bf5484f97 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^d_c^>!3HEx3Z6Ryq!^2X+?^QKos)S9Y_=f;# zCLjg@79iGu(ja!t&RbE8K-$C8#W6%fH0j6x|MhAD^=wHw510cCdKozxe&#sX%xCm? zaEWCKQ}c6!S_e6P0eObbCKDkhc?YS+t|tvYgnSG&rREcSm` nnQWcQ9k)1oD9o4aP-kYCd!YJE*P7>ZKqh;-`njxgN@xNA(riq} literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video@2x.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b11ca274122e87a9285f1d2f885da319a99e2d00 GIT binary patch literal 413 zcmeAS@N?(olHy`uVBq!ia0vp^GC(ZA!3HE*&&$6DQjEnx?oJHr&dIz4aySb-B8wRq z#8g3;(KATp15i*V)5SjoNHYO32yg(g29yS|x6Im^b{t4Ic)B=-cmNofwwE8-W;${(TrFh!ST-S5(ZNUa!{Kzr3k94CcAT47QXbk0G&>b=PH%N6 zzS{Uh@l4Hx)+-G18zMPOZpd}qSBiEp=5CzU!u-)c<+MZ2tOyR1?M!!-B<8;oW8$61 zW-KG^%gw#}(yi&v(>!s={zX&Dhlh?_yE6TY!MN_O}o+|kLpz@<>4 k!}fyifn)5elGz@eWXS)zPQ2cr2Na47p00i_>zopr0DRksn*aa+ literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video@3x.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewCollectionViewCell-video.imageset/PreviewCollectionViewCell-video@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..87d0538fc529e57a4d09e17b3971d8a97784c39f GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^T0ktp!3HFI3iJO0DaPU;cPEB*=VV?2Ih+L^k;M!Q ziWVTu=sL|X0VpVw>Ea&(q?v#i1bBd014@I~zb@>&6%3@0dAc};L~x$Da*^|pfxxkk zkD`CS;oy5HqxXpG6_ehgTi82a6Rayzbu;6B?-4GV9IB z-jbBQAo;Js_oLp=44M-=VetgsofG1x{W4EpIOihkJQm?E3tSs-^)^0=oRnR{x$1oI zqIb><6T+7G1~#4h>c6bE_;nt~l;-SDKXMc@HvVE`-K2P4=0*O32iuPP+4U}<;QhzR zyN{Nf7v*w!{CrN+nyu0z0r`I-4(xc(`L=gH$EJDn0!~l4ThGYA@c;jV&y!q$J~|EZ zQSuLe_X7uv~Pa)2`Cz<`q z!hqvO%(7OE6O!5QEZk7SU6NrZ@c-!32ab;eGG4GT%KqY=o$Sc>x7oLeEvY_XVS7K@ zt!&OC>o2}#xBSAlOQHA2_Yal=k$f5ZxdaxA#4EI$T|SZc;+UC|b(?_n3dyBEm@KDo zcl0ls?UibGqDIfD&v`ogt48to1j`i;$`jaBnX{HgPOwz??C`8;k#$pqU4Xu@fIkC6 Y-P{A}=KQtcKyNX4y85}Sb4q9e0Exre7XSbN literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/Contents.json b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/Contents.json new file mode 100644 index 0000000..3abba0e --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "PreviewSupplementaryView-Checkmark-Selected.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "PreviewSupplementaryView-Checkmark-Selected@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "PreviewSupplementaryView-Checkmark-Selected@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected.png new file mode 100644 index 0000000000000000000000000000000000000000..8d3d970d7d2d945023e2fa6392a658773e288ac2 GIT binary patch literal 713 zcmV;)0yh1LP)Px#9BD*PQ~&?~0ssI2000003jhEBC;$Ke3jhEB3jhECOdWGDIRF3w7)eAyR7ee+ zQoB;aFc4G`3QC}gE#2zzIaGAe(lRta1^J)A40MpcfR6xD@du<~&q$0JB{sw}8lCTU zSNAez!`HU$K@d5Qz*7<|c~>04+_F&pT$+giID9BwG`k;LC7=Z~AFaYRn^sI5MV z&pQk-Q%?1>H+Oz5o=*HSdo zZA8nHY~Q73{;Mr?UTgUUwC$bSGVAz!VPA*foJ;=|OcqC+#a`iQ&sD427M6d;>ED&$ zUvKvHG{Jwe(!)MSH%V8~F#X5q{7FAJX8(w;;pJ6a7@cOAPBA7{;zOc}>GoXkZnPZ! z?-b(DJtmsD6DGU*0ssL2{~$#~3jhECH%UZ6RGm{hPQySDog#{8p(3$&W<1MvH~`R5 z0)h%6$cX|13Pev2mms3!1VF%?{Pp4(4wa4o=jM$Ej8)<5$+-%Ht*5t+|>XqsT)vK7}(88p`GDDs#p z{%Jsh`y$9Z!Ig9iTEC*hs}vk)ps`DI`{rB?D5S_t^c@E`Yb1I&6{#+>EXzB~OLFfV zvUF+Q289qJw*TOrI<}o}_?0Zs90v+{?f^W}T~!qMB^vw8`*`{!c?~qZ`Lq27W6SYr v!3>}Hocks6OH(e`9`i9pm(}UFuKfsetyh6Ks00000NkvXXu0mjfc49db literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected@2x.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4a09d619d78519edf0b4ecff538ab5aa56e4ba54 GIT binary patch literal 1566 zcmV+(2I2XMP)Px#32;bRa{vGqB>(^xB>_oNB=7(L032yVPgDQ^00IC20000002TlM04M+e02TlM z02TlM0_Z38$Z-Gw0<=j)K~z`?yqC+0)Ib!5(=F{nMCq0W&81Ey!3+2VK7fd#E(B2! zap85Z;95Zt^a%u4gSZfNA?QjOaKH!f0xkr_l{ds2I%=!`U#S|0&{Natq&pCjRGssm zFDG?534$6&uh(0XDYZLKy)_oWs7^Xb4j^Ms90;I(G%7q(eMM%1MFncQjSfvFNQ_j&l1Tt zpEm0iu(4p8H-%M>wU%#y;^vXhv5CH_ur4Nm=g7#~J8-)ifG;?MNnFQ;B@4?}lT_}0 zpuc12W7#(eP-@nJr9UT}VHCL=U=}{-1J=E*>}>j|3rimU7?=#>7mOMHz=uhcj!nQ4 zn3K%_;~z1=jVbBS?kmby(6P$V6s(QeCNPpa_y+(0|Nq{?(@y{Z0^3PMK~%+;ON-P% z5XU3pco31%kr|Tiu1=!p!4IHcz*PnjT|`mDtB<>=SHT7Eg5N-0_TqvE6^|bFrg+(d zCvgSARawF3`uJC;J4~`kHnTGs2YQn3s;>H_(p_EgV$wg+{(7Fb1#Qhw2l`+{dNK6< zeQSgz16s-{%=yN4(N-v+LnW$phc~mWNYSc?zh&+SA$I0xE2Y{I(I>0?t`2kquwK+| z?=TFcKYJWK?!;0a$OCgfR_X#C>USOJCSaLC`+C1&RP-7V*7FHHO|!7*R|mQ&SmuH4 z&B{}n}lWmp`@G47%IBW^iv72UT|<_*CObqVVNaX^xQ_c?{&M~ zZM>s-o%+5n%V6Dj2AcHyF=qqkCcR22eY=OgcRHQzMi49gz()Ccs#$R}2+i}*#*w-T zJ;K-3gpKA>1ugUu<5&pAp&1rA_iGX`b*mPvQ^MpsX{0BxJg^KdrIA(ouHzW$>LShHyb*i7 z-tM6c)KKP(1l#wG5BNcCGhAfzK2R&1hB31d@wz_RJYDN>$=k~HTal#8uxaY?WP{P! zoX*C&oIQ~89=j;O_!6RjqfYIS_lW!|VCx!eymj^f{S+S%d-A#?_hUgP+=s+>#HP|Cx+QLu3y0%j4fnvc^Trs1B)@D}Dd!u+5-XB5Bx0CCF_9NT%3 Q!vFvP07*qoM6N<$f|JbOzW@LL literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected@3x.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark-Selected.imageset/PreviewSupplementaryView-Checkmark-Selected@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2f42084a8a43662522c860d13530ddd1bd95532c GIT binary patch literal 2423 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 P00000NkvXXu0mjfmuM4r literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark@2x.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..020f9705ba907ddcb2f2d4903fccd1c8f63f1cf6 GIT binary patch literal 1394 zcmV-&1&#WNP)Px#32;bRa{vGqB>(^xB>_oNB=7(L032yVPgDQ^00IC20000002TlM04M+e02TlM z02TlM0dWMx5jW~zE-@B{oI5-}bGF%ZOq zAMvi>SwRr=7YLq2auDMokerl-EcgRV0yzkZw?q%3f*W1+Rc-ew!!kRQU3;LJ>F(-R zuU~g{*95@?PqW!PloFlIVt$Y@uVut|G2ayeNxOZ*Dp&_* zT~{Csk4s-l<_>JvWsDmS;#*m4=F9poZI{9+z+X8>DVz5R^DSmRS{lR}nwB|&3El+8 zJBNpN$F$AKs#qiKvHX{y%2x#^-pz=v!>}>ZxLRWalfDYv9l?f=Z@|7>4I*caWxTIM z1(5k^6h+OP$;4G6ngQ7-&W{8zK&$U zDdO28N7L*>P@f)dzk$-@;W4{~p|T#yI%Y!JDLr;ir%`kaTj9%qFfBR|-)|d?8i<9b z2bSZd-9t;hN#_0i6NsIBpVo1FU9el>V;F{qM;du-l+y!z^vD}^xzsSDH>z%IZg}KX z=n5iUvm$Q7@b6KFKs#eQKA_`3A&TG5hTN*c&E_5h?@;%ds!Md+FQ4(=Bn41z%*$%s zYPAlc;X6q8ag&APA^ciMz5;HNF!eOC%5c`o43ONs_DiL_HxTZs%E-L~cdLQ$z48!# zEhT+bQRVgn`xRv$@p->A%6pT5Q;y850itkQDmeE}m516G0Tm zSH$!nMXHg6&CI;n-4;Cb@9+nq6dQ`7|3KBds8^wa_k#a{t@L8RgG!G*^w!c#51vYM zYm2m?t*zGYd%F|ZkZzNZCL7r7&b*oTKKq@SH?v+u_7AQz&-1R~%IohcGlqsvJ^bx) zK`C`Jue9OV*bMo7c1;FN=6mZWg zaG>ceGX{pVmaa8ys zW0w+@U*`=tGUjE>M$1h$tL%NQg!Bzmjx-I!e<(oAZ2=~#rf@JV*4Ypcy+|2`SO~S9 zOVr&2#+4LGsAwiJ?qMz$Q^p|_DwWDDjQFmIXv}O|1mxsz+yKMyscnM+R)$0$69HGw z4T}{Sq0xc7)extKn+j0)FjQ*dTwpdt+CEO+>@+ZDDzot=7@=$xpeMpW^t7W8ZfD{A zJVIU~XM zqQpQPoNc;OwlxOM8js*i79xggKgrYm*jx&srswb}=ka)f(UaErJ(W3oAmx2^D!_RI z>c8pb?1B8M;OiB9>^Ogb{*Dib@t)waIz@^ex*d^&A<#brU*jVx=6sDm0yyErM}aR% z{-|S{w2`)QkU5k7WH;EB6|*lkIg(=DaTakZb$XXReArU-05Iw8wl8!UPWWgVXnmI# z3Kq_1z-(ctc{@Fp3(s7KQK+-R{G!|^!{vph|5O;1V=L)c>Hq)$07*qoM6N<$g57b4 A)&Kwi literal 0 HcmV?d00001 diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark@3x.png b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Images.xcassets/PreviewSupplementaryView-Checkmark.imageset/PreviewSupplementaryView-Checkmark@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..99021d7930182f6ed089b73aac3cbd1712747d0a GIT binary patch literal 2136 zcmV-e2&eanP)Px#32;bRa{vG#H~;`4H~~eLF<<}y032yVPgDQ^00IC20000003iSX04M+e03iSX z03iSX1R7#3;)VbK1LjFYK~#7FK&MoNM35&a$X0HJPG%U z?@`C30~K59u0U+gL1w=mHUuN{3~s$%cYl@iIhM5s3H0%FJ4Amro1I&!otAP$u*7J* zDd}9$2u5kImJT8)ffwuoA@4&r4fB*8L0#=8h|`rA^-sYL5u10D$>f6Ct(z;6N~Pw* zwt-UHWR8=v)}CDnzo9HO){23r5Z(G(T4XO3L!UdaAam}wFy3p!K8nq80fop}r$vO^# zZ~FQ`#9LLt%Tm80rZ0Sss_^omjtA4pW`!z5o)|;nteD~t!b$*hUg7qx2Kc~J74R8g zP&&@<81%s+ZgI%4Ejr~F5S@-Q_#igqiIWO9=L`d0a9iu z4+Z@&K*BFY1f>3lsZ){B0Vh!Zn=$zp00960r{e4a000ByNklMDcYrDtJ;4 ziW(mw5=e-UDC$>}?N09_OZF9acZ9KfySjVo`=+Y8x;sulY6j0=ejLYHiYF@nmiUtX zFm5g#{P#l>;dx#>DlD|Nwyw~)QBF8MsSmm#+1^f3Awme@YTSXO5hoyep&L{}ZHo#K zfs~syZg|COCy;7DH$ZqIDn$4m9o4vfqPvI@s@pV3*%KKe(sB1XzEDTzh)_e3A%f_h z#+{V%xRXdEJlz0anF0~92$0bP%o7^7l+q6|!#&>W#-tD(^-csOXuHPCtERyVBCcsc zQmQLPP^T5FlovE!1j>E`)0eVS3s8Uex)Hmmaf{jSPOzF-@G>*;NxyA&6P=_@x5b`_e zy6f^nNMBmiHzXS^c?Z;h&~Is3Wv>(qN)g)H+LpsAK5O*&8s5Z;I_uYD@8mW zUzvA+7AheQ=z&}!&*;*!S}U=aI%Q*lyB{hDLm=p?HNgyWi#-KRPz9Y~&AWiXtc09F z7o%1)Tx8ggA!*VVVoNa-{f{x^(njcRHdfeEyi$%@R+KK`&Qz+878zr;Kn4+Qg3hCs z-XkR+LsC1fN5nM;ys(nVYIc*9J6M)LXwFT-yAT?zhCCycC)_cvz`Ah?P%cZzWNtQQ&~y8R2twb(qpr-( zi}afhVL3NQ*NI-191|9xe=K8Z4R6VKZ?c#hHN>eM0RPA)fa`GCzM@x$1%S`$5++^N z8HQE}vE&)cFrX6GhfT1)eIWg@exE6ENdxORn5F1qG=%B6p!4uYvr#jOVfo^mK4m4% zCFm2w*YCiWzRYfD%^zAKzZBTPaBu8>S z3qZ_S4Gs9zJjQiyN6mq-}k(=7YG zH%Rco2)^VQnDZ_8^)Sl!D91n&yVEq+Q*FZlJ%GO5d<(}%h?Ull=l=)I7IX5X6|tBA O0000 contentSize.width + contentInset.right + } + + var imagePreviewLayout: PreviewCollectionViewLayout { + return collectionViewLayout as! PreviewCollectionViewLayout + } + + // MARK: - Initialization + + init() { + super.init(frame: CGRectZero, collectionViewLayout: PreviewCollectionViewLayout()) + + initialize() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + private func initialize() { + panGestureRecognizer.addTarget(self, action: "handlePanGesture:") + } + + // MARK: - Panning + + @objc private func handlePanGesture(gestureRecognizer: UIPanGestureRecognizer) { + if gestureRecognizer.state == .Ended { + let translation = gestureRecognizer.translationInView(self) + if translation == CGPoint() { + if !bouncing { + let possibleIndexPath = indexPathForItemAtPoint(gestureRecognizer.locationInView(self)) + if let indexPath = possibleIndexPath { + selectItemAtIndexPath(indexPath, animated: false, scrollPosition: .None) + delegate?.collectionView?(self, didSelectItemAtIndexPath: indexPath) + } + } + } + } + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewCell.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewCell.swift new file mode 100644 index 0000000..0ed31e5 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewCell.swift @@ -0,0 +1,75 @@ +// +// PreviewCollectionViewCell.swift +// ImagePickerSheet +// +// Created by Laurin Brandner on 06/09/14. +// Copyright (c) 2014 Laurin Brandner. All rights reserved. +// + +import UIKit + +class PreviewCollectionViewCell: UICollectionViewCell { + + let imageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .ScaleAspectFill + imageView.clipsToBounds = true + + return imageView + }() + + let videoIndicatorView: UIImageView = { + let imageView = UIImageView(image: videoImage) + imageView.hidden = true + + return imageView + }() + + private class var videoImage: UIImage? { + let bundle = NSBundle(forClass: ImagePickerSheetController.self) + let image = UIImage(named: "PreviewCollectionViewCell-video", inBundle: bundle, compatibleWithTraitCollection: nil) + + return image + } + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + + initialize() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + private func initialize() { + addSubview(imageView) + addSubview(videoIndicatorView) + } + + // MARK: - Other Methods + + override func prepareForReuse() { + super.prepareForReuse() + + imageView.image = nil + videoIndicatorView.hidden = true + } + + // MARK: - Layout + + override func layoutSubviews() { + super.layoutSubviews() + + imageView.frame = bounds + + let videoIndicatViewSize = videoIndicatorView.image?.size ?? CGSize() + let inset: CGFloat = 4 + let videoIndicatorViewOrigin = CGPoint(x: bounds.minX + inset, y: bounds.maxY - inset - videoIndicatViewSize.height) + videoIndicatorView.frame = CGRect(origin: videoIndicatorViewOrigin, size: videoIndicatViewSize) + } +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewLayout.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewLayout.swift new file mode 100644 index 0000000..511405a --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewLayout.swift @@ -0,0 +1,156 @@ +// +// PreviewCollectionViewLayout.swift +// ImagePickerSheet +// +// Created by Laurin Brandner on 06/09/14. +// Copyright (c) 2014 Laurin Brandner. All rights reserved. +// + +import UIKit + +class PreviewCollectionViewLayout: UICollectionViewFlowLayout { + + var invalidationCenteredIndexPath: NSIndexPath? + + var showsSupplementaryViews: Bool = true { + didSet { + invalidateLayout() + } + } + + private var layoutAttributes = [UICollectionViewLayoutAttributes]() + private var contentSize = CGSizeZero + + // MARK: - Initialization + + override init() { + super.init() + + initialize() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + private func initialize() { + scrollDirection = .Horizontal + } + + // MARK: - Layout + + override func prepareLayout() { + super.prepareLayout() + + layoutAttributes.removeAll(keepCapacity: false) + contentSize = CGSizeZero + + if let collectionView = collectionView, + dataSource = collectionView.dataSource, + delegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout { + var origin = CGPoint(x: sectionInset.left, y: sectionInset.top) + let numberOfSections = dataSource.numberOfSectionsInCollectionView?(collectionView) ?? 0 + + for s in 0 ..< numberOfSections { + let indexPath = NSIndexPath(forItem: 0, inSection: s) + let size = delegate.collectionView?(collectionView, layout: self, sizeForItemAtIndexPath: indexPath) ?? CGSizeZero + + let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) + attributes.frame = CGRect(origin: origin, size: size) + attributes.zIndex = 0 + + layoutAttributes.append(attributes) + + origin.x = attributes.frame.maxX + sectionInset.right + } + + contentSize = CGSize(width: origin.x, height: collectionView.frame.height) + } + } + + override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { + return true + } + + override func collectionViewContentSize() -> CGSize { + return contentSize + } + + override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint { + var contentOffset = proposedContentOffset + if let indexPath = invalidationCenteredIndexPath { + if let collectionView = collectionView { + let frame = layoutAttributes[indexPath.section].frame + contentOffset.x = frame.midX - collectionView.frame.width / 2.0 + + contentOffset.x = max(contentOffset.x, -collectionView.contentInset.left) + contentOffset.x = min(contentOffset.x, collectionViewContentSize().width - collectionView.frame.width + collectionView.contentInset.right) + } + invalidationCenteredIndexPath = nil + } + + return super.targetContentOffsetForProposedContentOffset(contentOffset) + } + + override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + return layoutAttributes + .filter { CGRectIntersectsRect(rect, $0.frame) } + .reduce([UICollectionViewLayoutAttributes]()) { memo, attributes in + if let supplementaryAttributes = layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: attributes.indexPath) { + return memo + [attributes, supplementaryAttributes] + } + return memo + } + } + + override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + return layoutAttributes[indexPath.section] + } + + override func layoutAttributesForSupplementaryViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + if let collectionView = collectionView, + delegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout, + itemAttributes = layoutAttributesForItemAtIndexPath(indexPath) { + + let inset = collectionView.contentInset + let bounds = collectionView.bounds + let contentOffset: CGPoint = { + var contentOffset = collectionView.contentOffset + contentOffset.x += inset.left + contentOffset.y += inset.top + + return contentOffset + }() + let visibleSize: CGSize = { + var size = bounds.size + size.width -= (inset.left+inset.right) + + return size + }() + let visibleFrame = CGRect(origin: contentOffset, size: visibleSize) + + let size = delegate.collectionView?(collectionView, layout: self, referenceSizeForHeaderInSection: indexPath.section) ?? CGSizeZero + let originX = max(itemAttributes.frame.minX, min(itemAttributes.frame.maxX - size.width, visibleFrame.maxX - size.width)) + + let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, withIndexPath: indexPath) + attributes.zIndex = 1 + attributes.hidden = !showsSupplementaryViews + attributes.frame = CGRect(origin: CGPoint(x: originX, y: itemAttributes.frame.minY), size: size) + + return attributes + } + + return nil + } + + override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + return layoutAttributesForItemAtIndexPath(itemIndexPath) + } + + override func finalLayoutAttributesForDisappearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + return layoutAttributesForItemAtIndexPath(itemIndexPath) + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewSupplementaryView.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewSupplementaryView.swift new file mode 100644 index 0000000..b35fc1b --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewSupplementaryView.swift @@ -0,0 +1,92 @@ +// +// PreviewSupplementaryView.swift +// ImagePickerSheet +// +// Created by Laurin Brandner on 06/09/14. +// Copyright (c) 2014 Laurin Brandner. All rights reserved. +// + +import UIKit + +class PreviewSupplementaryView: UICollectionReusableView { + + private let button: UIButton = { + let button = UIButton() + button.tintColor = .whiteColor() + button.userInteractionEnabled = false + button.setImage(PreviewSupplementaryView.checkmarkImage, forState: .Normal) + button.setImage(PreviewSupplementaryView.selectedCheckmarkImage, forState: .Selected) + + return button + }() + + var buttonInset = UIEdgeInsetsZero + + var selected: Bool = false { + didSet { + button.selected = selected + reloadButtonBackgroundColor() + } + } + + class var checkmarkImage: UIImage? { + let bundle = NSBundle(forClass: ImagePickerSheetController.self) + let image = UIImage(named: "PreviewSupplementaryView-Checkmark", inBundle: bundle, compatibleWithTraitCollection: nil) + + return image?.imageWithRenderingMode(.AlwaysTemplate) + } + + class var selectedCheckmarkImage: UIImage? { + let bundle = NSBundle(forClass: ImagePickerSheetController.self) + let image = UIImage(named: "PreviewSupplementaryView-Checkmark-Selected", inBundle: bundle, compatibleWithTraitCollection: nil) + + return image?.imageWithRenderingMode(.AlwaysTemplate) + } + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + + initialize() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + private func initialize() { + addSubview(button) + } + + // MARK: - Other Methods + + override func prepareForReuse() { + super.prepareForReuse() + + selected = false + } + + override func tintColorDidChange() { + super.tintColorDidChange() + + reloadButtonBackgroundColor() + } + + private func reloadButtonBackgroundColor() { + button.backgroundColor = (selected) ? tintColor : nil + } + + // MARK: - Layout + + override func layoutSubviews() { + super.layoutSubviews() + + button.sizeToFit() + button.frame.origin = CGPointMake(buttonInset.left, CGRectGetHeight(bounds)-CGRectGetHeight(button.frame)-buttonInset.bottom) + button.layer.cornerRadius = CGRectGetHeight(button.frame) / 2.0 + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetActionCollectionViewCell.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetActionCollectionViewCell.swift new file mode 100644 index 0000000..c5feefc --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetActionCollectionViewCell.swift @@ -0,0 +1,70 @@ +// +// SheetActionCollectionViewCell.swift +// ImagePickerSheetController +// +// Created by Laurin Brandner on 26/08/15. +// Copyright © 2015 Laurin Brandner. All rights reserved. +// + +import UIKit + +let KVOContext = UnsafeMutablePointer<()>() + +class SheetActionCollectionViewCell: SheetCollectionViewCell { + + lazy private(set) var textLabel: UILabel = { + let label = UILabel() + label.textColor = self.tintColor + label.textAlignment = .Center + + self.addSubview(label) + + return label + }() + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + initialize() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + initialize() + } + + private func initialize() { + textLabel.addObserver(self, forKeyPath: "text", options: NSKeyValueObservingOptions(rawValue: 0), context: KVOContext) + } + + deinit { + textLabel.removeObserver(self, forKeyPath: "text") + } + + // MARK: - Accessibility + + override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) { + guard context == KVOContext else { + super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) + return + } + + accessibilityLabel = textLabel.text + } + + // MARK: - + + override func tintColorDidChange() { + super.tintColorDidChange() + + textLabel.textColor = tintColor + } + + override func layoutSubviews() { + super.layoutSubviews() + + textLabel.frame = UIEdgeInsetsInsetRect(bounds, backgroundInsets) + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewCell.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewCell.swift new file mode 100644 index 0000000..a5eeacf --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewCell.swift @@ -0,0 +1,173 @@ +// +// SheetCollectionViewCell.swift +// ImagePickerSheetController +// +// Created by Laurin Brandner on 24/08/15. +// Copyright © 2015 Laurin Brandner. All rights reserved. +// + +import UIKit + +enum RoundedCorner { + case All(CGFloat) + case Top(CGFloat) + case Bottom(CGFloat) + case None +} + +class SheetCollectionViewCell: UICollectionViewCell { + + var backgroundInsets = UIEdgeInsets() { + didSet { + reloadMask() + reloadSeparator() + setNeedsLayout() + } + } + + var roundedCorners = RoundedCorner.None { + didSet { + reloadMask() + } + } + + var separatorVisible = false { + didSet { + reloadSeparator() + } + } + + var separatorColor = UIColor.blackColor() { + didSet { + separatorView?.backgroundColor = separatorColor + } + } + + var separatorHeight: CGFloat = 1 { + didSet { + setNeedsLayout() + } + } + + private var separatorView: UIView? + + override var highlighted: Bool { + didSet { + reloadBackgroundColor() + } + } + + var highlightedBackgroundColor: UIColor = .clearColor() { + didSet { + reloadBackgroundColor() + } + } + + var normalBackgroundColor: UIColor = .clearColor() { + didSet { + reloadBackgroundColor() + } + } + + private var needsMasking: Bool { + guard backgroundInsets == UIEdgeInsets() else { + return true + } + + switch roundedCorners { + case .None: + return false + default: + return true + } + } + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + initialize() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + initialize() + } + + private func initialize() { + layoutMargins = UIEdgeInsets() + } + + // MARK: - Layout + + override func layoutSubviews() { + super.layoutSubviews() + + reloadMask() + + separatorView?.frame = CGRect(x: bounds.minY, y: bounds.maxY - separatorHeight, width: bounds.width, height: separatorHeight) + } + + // MARK: - Mask + + private func reloadMask() { + if needsMasking && layer.mask == nil { + let maskLayer = CAShapeLayer() + maskLayer.frame = bounds + maskLayer.lineWidth = 0 + maskLayer.fillColor = UIColor.blackColor().CGColor + + layer.mask = maskLayer + } + + let layerMask = layer.mask as? CAShapeLayer + layerMask?.frame = bounds + layerMask?.path = maskPathWithRect(UIEdgeInsetsInsetRect(bounds, backgroundInsets), roundedCorner: roundedCorners) + } + + private func maskPathWithRect(rect: CGRect, roundedCorner: RoundedCorner) -> CGPathRef { + let radii: CGFloat + let corners: UIRectCorner + + switch roundedCorner { + case .All(let value): + corners = .AllCorners + radii = value + case .Top(let value): + corners = [.TopLeft, .TopRight] + radii = value + case .Bottom(let value): + corners = [.BottomLeft, .BottomRight] + radii = value + case .None: + return UIBezierPath(rect: rect).CGPath + } + + return UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radii, height: radii)).CGPath + } + + // MARK: - Separator + + private func reloadSeparator() { + if separatorVisible && backgroundInsets.bottom < separatorHeight { + if separatorView == nil { + let view = UIView() + view.backgroundColor = separatorColor + + addSubview(view) + separatorView = view + } + } + else { + separatorView?.removeFromSuperview() + separatorView = nil + } + } + + // MARK - Background + + private func reloadBackgroundColor() { + backgroundColor = highlighted ? highlightedBackgroundColor : normalBackgroundColor + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewLayout.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewLayout.swift new file mode 100644 index 0000000..49b0041 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewLayout.swift @@ -0,0 +1,99 @@ +// +// SheetCollectionViewLayout.swift +// ImagePickerSheetController +// +// Created by Laurin Brandner on 26/08/15. +// Copyright © 2015 Laurin Brandner. All rights reserved. +// + +import UIKit + +class SheetCollectionViewLayout: UICollectionViewLayout { + + private var layoutAttributes = [[UICollectionViewLayoutAttributes]]() + private var invalidatedLayoutAttributes: [[UICollectionViewLayoutAttributes]]? + private var contentSize = CGSizeZero + + // MARK: - Layout + + override func prepareLayout() { + super.prepareLayout() + + layoutAttributes.removeAll(keepCapacity: false) + contentSize = CGSizeZero + + if let collectionView = collectionView, + dataSource = collectionView.dataSource, + delegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout { + let sections = dataSource.numberOfSectionsInCollectionView?(collectionView) ?? 0 + var origin = CGPoint() + + for section in 0 ..< sections { + var sectionAttributes = [UICollectionViewLayoutAttributes]() + let items = dataSource.collectionView(collectionView, numberOfItemsInSection: section) + let indexPaths = (0 ..< items).map { NSIndexPath(forItem: $0, inSection: section) } + + for indexPath in indexPaths { + let size = delegate.collectionView?(collectionView, layout: self, sizeForItemAtIndexPath: indexPath) ?? CGSizeZero + + let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) + attributes.frame = CGRect(origin: origin, size: size) + + sectionAttributes.append(attributes) + origin.y = attributes.frame.maxY + } + + layoutAttributes.append(sectionAttributes) + } + + contentSize = CGSize(width: collectionView.frame.width, height: origin.y) + } + } + + override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { + return true + } + + override func invalidateLayout() { + invalidatedLayoutAttributes = layoutAttributes + super.invalidateLayout() + } + + override func collectionViewContentSize() -> CGSize { + return contentSize + } + + override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + return layoutAttributes.reduce([], combine: +) + .filter { CGRectIntersectsRect(rect, $0.frame) } + } + + private func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath, allAttributes: [[UICollectionViewLayoutAttributes]]) -> UICollectionViewLayoutAttributes? { + guard allAttributes.count > indexPath.section && allAttributes[indexPath.section].count > indexPath.item else { + return nil + } + + return allAttributes[indexPath.section][indexPath.item] + } + + private func invalidatedLayoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + guard let invalidatedLayoutAttributes = invalidatedLayoutAttributes else { + return nil + } + + return layoutAttributesForItemAtIndexPath(indexPath, allAttributes: invalidatedLayoutAttributes) + } + + override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + return layoutAttributesForItemAtIndexPath(indexPath, allAttributes: layoutAttributes) + } + + override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + return invalidatedLayoutAttributesForItemAtIndexPath(itemIndexPath) ?? layoutAttributesForItemAtIndexPath(itemIndexPath) + } + + override func finalLayoutAttributesForDisappearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + return layoutAttributesForItemAtIndexPath(itemIndexPath) + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetController.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetController.swift new file mode 100644 index 0000000..044a8f5 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetController.swift @@ -0,0 +1,265 @@ +// +// SheetController.swift +// ImagePickerSheetController +// +// Created by Laurin Brandner on 27/08/15. +// Copyright © 2015 Laurin Brandner. All rights reserved. +// + +import UIKit + +private let defaultInset: CGFloat = 10 + +class SheetController: NSObject { + + private(set) lazy var sheetCollectionView: UICollectionView = { + let layout = SheetCollectionViewLayout() + let collectionView = UICollectionView(frame: CGRect(), collectionViewLayout: layout) + collectionView.dataSource = self + collectionView.delegate = self + collectionView.accessibilityIdentifier = "ImagePickerSheet" + collectionView.backgroundColor = .clearColor() + collectionView.alwaysBounceVertical = false + collectionView.registerClass(SheetPreviewCollectionViewCell.self, forCellWithReuseIdentifier: NSStringFromClass(SheetPreviewCollectionViewCell.self)) + collectionView.registerClass(SheetActionCollectionViewCell.self, forCellWithReuseIdentifier: NSStringFromClass(SheetActionCollectionViewCell.self)) + + return collectionView + }() + + var previewCollectionView: PreviewCollectionView + + private(set) var actions = [ImagePickerAction]() + + var actionHandlingCallback: (() -> ())? + + private(set) var previewHeight: CGFloat = 0 + var numberOfSelectedImages = 0 + + var preferredSheetHeight: CGFloat { + return allIndexPaths().map { self.sizeForSheetItemAtIndexPath($0).height } + .reduce(0, combine: +) + } + + var preferredSheetWidth: CGFloat { + guard #available(iOS 9, *) else { + return sheetCollectionView.bounds.width + } + return sheetCollectionView.bounds.width - 2 * defaultInset + } + + // MARK: - Initialization + + init(previewCollectionView: PreviewCollectionView) { + self.previewCollectionView = previewCollectionView + + super.init() + } + + // MARK: - Data Source + // These methods are necessary so that no call cycles happen when calculating some design attributes + + private func numberOfSections() -> Int { + return 2 + } + + private func numberOfItemsInSection(section: Int) -> Int { + if section == 0 { + return 1 + } + + return actions.count + } + + private func allIndexPaths() -> [NSIndexPath] { + let s = numberOfSections() + return (0 ..< s).map { (self.numberOfItemsInSection($0), $0) } + .flatMap { numberOfItems, section in + (0 ..< numberOfItems).map { NSIndexPath(forItem: $0, inSection: section) } + } + } + + private func sizeForSheetItemAtIndexPath(indexPath: NSIndexPath) -> CGSize { + let height: CGFloat = { + if indexPath.section == 0 { + return previewHeight + } + + let actionItemHeight: CGFloat + + if #available(iOS 9, *) { + actionItemHeight = 57 + } + else { + actionItemHeight = 50 + } + + let insets = attributesForItemAtIndexPath(indexPath).backgroundInsets + return actionItemHeight + insets.top + insets.bottom + }() + + return CGSize(width: sheetCollectionView.bounds.width, height: height) + } + + // MARK: - Design + + private func attributesForItemAtIndexPath(indexPath: NSIndexPath) -> (corners: RoundedCorner, backgroundInsets: UIEdgeInsets) { + guard #available(iOS 9, *) else { + return (.None, UIEdgeInsets()) + } + + let cornerRadius: CGFloat = 13 + let innerInset: CGFloat = 4 + var indexPaths = allIndexPaths() + + guard indexPaths.first != indexPath else { + return (.Top(cornerRadius), UIEdgeInsets(top: 0, left: defaultInset, bottom: 0, right: defaultInset)) + } + + let cancelIndexPath = actions.indexOf { $0.style == ImagePickerActionStyle.Cancel } + .map { NSIndexPath(forItem: $0, inSection: 1) } + + + if let cancelIndexPath = cancelIndexPath { + if cancelIndexPath == indexPath { + return (.All(cornerRadius), UIEdgeInsets(top: innerInset, left: defaultInset, bottom: defaultInset, right: defaultInset)) + } + + indexPaths.removeLast() + + if indexPath == indexPaths.last { + return (.Bottom(cornerRadius), UIEdgeInsets(top: 0, left: defaultInset, bottom: innerInset, right: defaultInset)) + } + } + else if indexPath == indexPaths.last { + return (.Bottom(cornerRadius), UIEdgeInsets(top: 0, left: defaultInset, bottom: defaultInset, right: defaultInset)) + } + + return (.None, UIEdgeInsets(top: 0, left: defaultInset, bottom: 0, right: defaultInset)) + } + + private func fontForAction(action: ImagePickerAction) -> UIFont { + guard #available(iOS 9, *), action.style == .Cancel else { + return UIFont.systemFontOfSize(21) + } + + return UIFont.boldSystemFontOfSize(21) + } + + // MARK: - Actions + + func reloadActionItems() { + sheetCollectionView.reloadSections(NSIndexSet(index: 1)) + } + + func addAction(action: ImagePickerAction) { + if action.style == .Cancel { + actions = actions.filter { $0.style != .Cancel } + } + + actions.append(action) + + if let index = actions.indexOf({ $0.style == .Cancel }) { + let cancelAction = actions.removeAtIndex(index) + actions.append(cancelAction) + } + + reloadActionItems() + } + + private func handleAction(action: ImagePickerAction) { + actionHandlingCallback?() + action.handle(numberOfSelectedImages) + } + + func handleCancelAction() { + let cancelAction = actions.filter { $0.style == ImagePickerActionStyle.Cancel } + .first + + if let cancelAction = cancelAction { + handleAction(cancelAction) + } + else { + actionHandlingCallback?() + } + } + + // MARK: - + + func setPreviewHeight(height: CGFloat, invalidateLayout: Bool) { + previewHeight = height + if invalidateLayout { + sheetCollectionView.collectionViewLayout.invalidateLayout() + } + } + +} + +extension SheetController: UICollectionViewDataSource { + + func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { + return numberOfSections() + } + + func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return numberOfItemsInSection(section) + } + + func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { + let cell: SheetCollectionViewCell + + if indexPath.section == 0 { + let previewCell = collectionView.dequeueReusableCellWithReuseIdentifier(NSStringFromClass(SheetPreviewCollectionViewCell.self), forIndexPath: indexPath) as! SheetPreviewCollectionViewCell + previewCell.collectionView = previewCollectionView + + cell = previewCell + } + else { + let action = actions[indexPath.item] + let actionCell = collectionView.dequeueReusableCellWithReuseIdentifier(NSStringFromClass(SheetActionCollectionViewCell.self), forIndexPath: indexPath) as! SheetActionCollectionViewCell + actionCell.textLabel.font = fontForAction(action) + actionCell.textLabel.text = numberOfSelectedImages > 0 ? action.secondaryTitle(numberOfSelectedImages) : action.title + + cell = actionCell + } + + cell.separatorVisible = (indexPath.section == 1) + + // iOS specific design + (cell.roundedCorners, cell.backgroundInsets) = attributesForItemAtIndexPath(indexPath) + if #available(iOS 9, *) { + cell.normalBackgroundColor = UIColor(white: 0.97, alpha: 1) + cell.highlightedBackgroundColor = UIColor(white: 0.92, alpha: 1) + cell.separatorColor = UIColor(white: 0.84, alpha: 1) + } + else { + cell.normalBackgroundColor = .whiteColor() + cell.highlightedBackgroundColor = UIColor(white: 0.85, alpha: 1) + cell.separatorColor = UIColor(white: 0.784, alpha: 1) + } + + return cell + } + +} + +extension SheetController: UICollectionViewDelegate { + + func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool { + return indexPath.section != 0 + } + + func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + collectionView.deselectItemAtIndexPath(indexPath, animated: true) + + handleAction(actions[indexPath.item]) + } + +} + +extension SheetController: UICollectionViewDelegateFlowLayout { + + func collectionView(collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { + return sizeForSheetItemAtIndexPath(indexPath) + } + +} diff --git a/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetPreviewCollectionViewCell.swift b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetPreviewCollectionViewCell.swift new file mode 100644 index 0000000..e097eb1 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetPreviewCollectionViewCell.swift @@ -0,0 +1,39 @@ +// +// SheetPreviewCollectionViewCell.swift +// ImagePickerSheetController +// +// Created by Laurin Brandner on 06/09/14. +// Copyright (c) 2014 Laurin Brandner. All rights reserved. +// + +import UIKit + +class SheetPreviewCollectionViewCell: SheetCollectionViewCell { + + var collectionView: PreviewCollectionView? { + willSet { + if let collectionView = collectionView { + collectionView.removeFromSuperview() + } + + if let collectionView = newValue { + addSubview(collectionView) + } + } + } + + // MARK: - Other Methods + + override func prepareForReuse() { + collectionView = nil + } + + // MARK: - Layout + + override func layoutSubviews() { + super.layoutSubviews() + + collectionView?.frame = UIEdgeInsetsInsetRect(bounds, backgroundInsets) + } + +} diff --git a/ios/Pods/ImagePickerSheetController/LICENSE b/ios/Pods/ImagePickerSheetController/LICENSE new file mode 100644 index 0000000..151fa72 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Laurin Brandner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ios/Pods/ImagePickerSheetController/README.md b/ios/Pods/ImagePickerSheetController/README.md new file mode 100644 index 0000000..ffe0949 --- /dev/null +++ b/ios/Pods/ImagePickerSheetController/README.md @@ -0,0 +1,56 @@ +# ImagePickerSheetController + +[![Twitter: @larcus94](https://img.shields.io/badge/contact-@larcus94-blue.svg?style=flat)](https://twitter.com/larcus94) +[![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/larcus94/ImagePickerSheetController/blob/master/LICENSE) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + +## About +ImagePickerSheetController is a component that replicates the custom photo action sheet in iMessage. It's very similar to UIAlertController which makes its usage simple and concise. + +![Screenshot](https://raw.githubusercontent.com/larcus94/ImagePickerSheetController/master/Screenshots/GoT.gif) + +## Usage +`ImagePickerSheetController` is similar to `UIAlertController` in its usage. + +### Example + +```swift +let controller = ImagePickerSheetController(mediaType: .ImageAndVideo) +controller.addAction(ImagePickerAction(title: NSLocalizedString("Take Photo Or Video", comment: "Action Title"), secondaryTitle: NSLocalizedString("Add comment", comment: "Action Title"), handler: { _ in + presentImagePickerController(.Camera) +}, secondaryHandler: { _, numberOfPhotos in + println("Comment \(numberOfPhotos) photos") +})) +controller.addAction(ImagePickerAction(title: NSLocalizedString("Photo Library", comment: "Action Title"), secondaryTitle: { NSString.localizedStringWithFormat(NSLocalizedString("ImagePickerSheet.button1.Send %lu Photo", comment: "Action Title"), $0) as String}, handler: { _ in + presentImagePickerController(.PhotoLibrary) +}, secondaryHandler: { _, numberOfPhotos in + println("Send \(controller.selectedImageAssets)") +})) +controller.addAction(ImagePickerAction(title: NSLocalizedString("Cancel", comment: "Action Title"), style: .Cancel, handler: { _ in + println("Cancelled") +})) + +presentViewController(controller, animated: true, completion: nil) +``` +It's recommended to use [stringsdict](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) to easily translate plural forms in any language. + +## Installation + +### CocoaPods +```ruby +pod "ImagePickerSheetController", "~> 0.9.1" +``` + +###Carthage +```objc +github "larcus94/ImagePickerSheetController" ~> 0.9.1 +``` + +## Requirements +ImagePickerSheetController is written in Swift and links against `Photos.framework`. It therefore requires iOS 8 or later. + +## Author +I'm Laurin Brandner, I'm on [Twitter](https://twitter.com/larcus94). + +## License +ImagePickerSheetController is licensed under the [MIT License](http://opensource.org/licenses/mit-license.php). diff --git a/ios/Pods/Manifest.lock b/ios/Pods/Manifest.lock new file mode 100644 index 0000000..e6e876b --- /dev/null +++ b/ios/Pods/Manifest.lock @@ -0,0 +1,10 @@ +PODS: + - ImagePickerSheetController (0.9.1) + +DEPENDENCIES: + - ImagePickerSheetController + +SPEC CHECKSUMS: + ImagePickerSheetController: 3c58c9fee6dcf36485222358a021f6b734f997ba + +COCOAPODS: 0.39.0 diff --git a/ios/Pods/Pods.xcodeproj/project.pbxproj b/ios/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..aee5f3c --- /dev/null +++ b/ios/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,573 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 079630E2D4FDD18DA1148E24A6D9F48C /* ImagePickerAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DBA2152DC4141AF0EE54E2DB10210B5 /* ImagePickerAction.swift */; }; + 180378212E28F7A112A87A43DF6E5F7F /* PreviewCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B67719E721B448F6065B50621081684A /* PreviewCollectionView.swift */; }; + 3343C7EF8FC7413A0A907F6FC5C78C74 /* SheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A35A3834BF674B5F1CDB72D9D646658 /* SheetController.swift */; }; + 363134533B7518E26FEB125E29D3BDF5 /* PreviewCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CE6E7CD62AF49861EC3F12442386C0 /* PreviewCollectionViewCell.swift */; }; + 37A5494E25A4BEB49274FD8644A6D194 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E36762FF8E4A4E113EEC970F71E699C /* Foundation.framework */; }; + 3BEBBF1BC29E28E275612602AD2CBC58 /* Pods-ReactNativeCameraKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F3AC07D2E4446CA38B0AFB55935D506 /* Pods-ReactNativeCameraKit-dummy.m */; }; + 5A97CB0EA725BF0EA48A2B3CBF199887 /* ImagePickerSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C525DEF5158DF542A9FAB0874C83A06E /* ImagePickerSheetController.swift */; }; + 5D0DE2F60AE2806F484AC6D0F53362A5 /* AnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2D98780222413EDBBD45C7302EC0BA8 /* AnimationController.swift */; }; + 65DDC4906B56C3C19A03B2EB4257435F /* ImagePickerSheetController-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3134E79C0CA7BE51D6DD42575AC4BD78 /* ImagePickerSheetController-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6700755A206C8136A97B20B9D2FA788C /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 697E2FB9C7768EDEA1457A96EDB78BE9 /* Photos.framework */; }; + 6FFF9F6BAB7E459AFFBE5C6B4343372C /* SheetActionCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFFC468480F371982DE65A908A41DA21 /* SheetActionCollectionViewCell.swift */; }; + 884AE123CAC9A5491C23AE729FE4832D /* SheetCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06F339EAACD2E9ED6A6119E816DC3AA /* SheetCollectionViewLayout.swift */; }; + 9180B8BA812802D78F860175B02387FF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F2C06E2463508844773E3E096A35A47C /* Images.xcassets */; }; + B8912CE08C66BD2B6189745EDB35F33F /* PreviewCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C00EDF48AC63BAA768D0A0B6E20C31B /* PreviewCollectionViewLayout.swift */; }; + CD78C10DADDEC6B5E39D47DFE8975B48 /* Pods-ReactNativeCameraKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B38237FA9EF751ED77E239C733829D /* Pods-ReactNativeCameraKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D1A2E5C864D0CB49A2E760B345A9852F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E36762FF8E4A4E113EEC970F71E699C /* Foundation.framework */; }; + E7B7BAB2FE1730965D067CE994FB7EC2 /* ImagePickerSheetController-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FD0EAA78B4A44CC82E24ED80A813BFDB /* ImagePickerSheetController-dummy.m */; }; + E8129D7EC7434F22247C35916CBAD0B8 /* PreviewSupplementaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C844465AE2EA77CFF17AA3699FFB79CD /* PreviewSupplementaryView.swift */; }; + EE75E9914DE58A76A5460938813EE4DC /* SheetCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 990E4D7FD59799C10E85A6487106B18B /* SheetCollectionViewCell.swift */; }; + F2E2DE1EC6D5DA0477EA29AF543017A2 /* SheetPreviewCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBE83F6A85A4DEAE74B5AD71A974CAE /* SheetPreviewCollectionViewCell.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + DDFBF28D1A8D92742997C008E7B80ED5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2AAAB9973850C35994DC04473435E1A3; + remoteInfo = ImagePickerSheetController; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 03E2CDD46BB9E1A4A66D0550179FDC2C /* Pods-ReactNativeCameraKit-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ReactNativeCameraKit-acknowledgements.markdown"; sourceTree = ""; }; + 0F3AC07D2E4446CA38B0AFB55935D506 /* Pods-ReactNativeCameraKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ReactNativeCameraKit-dummy.m"; sourceTree = ""; }; + 12CE2841A34BEB5906032E3980F43037 /* ImagePickerSheetController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ImagePickerSheetController-prefix.pch"; sourceTree = ""; }; + 1E0275907FE8E85889145D3B97263935 /* ImagePickerSheetController.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ImagePickerSheetController.xcconfig; sourceTree = ""; }; + 2C00EDF48AC63BAA768D0A0B6E20C31B /* PreviewCollectionViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewCollectionViewLayout.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewLayout.swift; sourceTree = ""; }; + 3134E79C0CA7BE51D6DD42575AC4BD78 /* ImagePickerSheetController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ImagePickerSheetController-umbrella.h"; sourceTree = ""; }; + 3CF582E27F74A69C6F871ED64816F6DE /* Pods-ReactNativeCameraKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ReactNativeCameraKit.release.xcconfig"; sourceTree = ""; }; + 4A35A3834BF674B5F1CDB72D9D646658 /* SheetController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SheetController.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetController.swift; sourceTree = ""; }; + 4EBE83F6A85A4DEAE74B5AD71A974CAE /* SheetPreviewCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SheetPreviewCollectionViewCell.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetPreviewCollectionViewCell.swift; sourceTree = ""; }; + 66B38237FA9EF751ED77E239C733829D /* Pods-ReactNativeCameraKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ReactNativeCameraKit-umbrella.h"; sourceTree = ""; }; + 68DF5BE345BF4A20C242226D8BDFC520 /* Pods-ReactNativeCameraKit-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ReactNativeCameraKit-frameworks.sh"; sourceTree = ""; }; + 697E2FB9C7768EDEA1457A96EDB78BE9 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; }; + 75CE6E7CD62AF49861EC3F12442386C0 /* PreviewCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewCollectionViewCell.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionViewCell.swift; sourceTree = ""; }; + 7AA7C40F5CD7AC6BF35E1B0065DA72C5 /* Pods-ReactNativeCameraKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-ReactNativeCameraKit.modulemap"; sourceTree = ""; }; + 9480CFCA0F9FB4526A047ED920A554BC /* Pods-ReactNativeCameraKit-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ReactNativeCameraKit-acknowledgements.plist"; sourceTree = ""; }; + 990E4D7FD59799C10E85A6487106B18B /* SheetCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SheetCollectionViewCell.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewCell.swift; sourceTree = ""; }; + 9DBA2152DC4141AF0EE54E2DB10210B5 /* ImagePickerAction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImagePickerAction.swift; path = ImagePickerSheetController/ImagePickerSheetController/ImagePickerAction.swift; sourceTree = ""; }; + 9E36762FF8E4A4E113EEC970F71E699C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + A2D98780222413EDBBD45C7302EC0BA8 /* AnimationController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimationController.swift; path = ImagePickerSheetController/ImagePickerSheetController/AnimationController.swift; sourceTree = ""; }; + AE1EF0EC94DA87361C0406DA6AC248C3 /* ImagePickerSheetController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ImagePickerSheetController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B67719E721B448F6065B50621081684A /* PreviewCollectionView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewCollectionView.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewCollectionView.swift; sourceTree = ""; }; + BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + BA9C090317F3F76F40B0CACF691929EE /* Pods-ReactNativeCameraKit-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ReactNativeCameraKit-resources.sh"; sourceTree = ""; }; + C525DEF5158DF542A9FAB0874C83A06E /* ImagePickerSheetController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImagePickerSheetController.swift; path = ImagePickerSheetController/ImagePickerSheetController/ImagePickerSheetController.swift; sourceTree = ""; }; + C844465AE2EA77CFF17AA3699FFB79CD /* PreviewSupplementaryView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewSupplementaryView.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/Preview/PreviewSupplementaryView.swift; sourceTree = ""; }; + CAE48460691A7F16DC3E2A8158DA8C1C /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CD097932506E41F66E1BB103B2080A8D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CDDDD47987996CE6E4F88ACE58031BA9 /* ImagePickerSheetController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = ImagePickerSheetController.modulemap; sourceTree = ""; }; + E06F339EAACD2E9ED6A6119E816DC3AA /* SheetCollectionViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SheetCollectionViewLayout.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetCollectionViewLayout.swift; sourceTree = ""; }; + EEF467F3FE90185318D7CC581BB160FA /* Pods-ReactNativeCameraKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ReactNativeCameraKit.debug.xcconfig"; sourceTree = ""; }; + F2C06E2463508844773E3E096A35A47C /* Images.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ImagePickerSheetController/ImagePickerSheetController/Images.xcassets; sourceTree = ""; }; + F831E4A5EFAFD16B864480C9C0F8E1E9 /* Pods_ReactNativeCameraKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReactNativeCameraKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FD0EAA78B4A44CC82E24ED80A813BFDB /* ImagePickerSheetController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ImagePickerSheetController-dummy.m"; sourceTree = ""; }; + FFFC468480F371982DE65A908A41DA21 /* SheetActionCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SheetActionCollectionViewCell.swift; path = ImagePickerSheetController/ImagePickerSheetController/Sheet/SheetActionCollectionViewCell.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 185CDE137F7E9E23F1CE9B518D47E7FB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D1A2E5C864D0CB49A2E760B345A9852F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B00AEE85F1051CEEC27A8D13F638E23C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 37A5494E25A4BEB49274FD8644A6D194 /* Foundation.framework in Frameworks */, + 6700755A206C8136A97B20B9D2FA788C /* Photos.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { + isa = PBXGroup; + children = ( + CF60819FDD9A8A1FDDBE8C01CFDB526F /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 755C1EE9F7841B918D05512036D6F60D /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + CB688DDE44D693E9312BCCFEF49508F5 /* Pods-ReactNativeCameraKit */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */, + 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, + EF0BF5064E61294AD74BCC8C19C17E70 /* Pods */, + AF7A76083693DFBE6F6696812B7370A6 /* Products */, + 755C1EE9F7841B918D05512036D6F60D /* Targets Support Files */, + ); + sourceTree = ""; + }; + 9531269308E2BE6B671DDE9564BFE996 /* Resources */ = { + isa = PBXGroup; + children = ( + F2C06E2463508844773E3E096A35A47C /* Images.xcassets */, + ); + name = Resources; + sourceTree = ""; + }; + AF7A76083693DFBE6F6696812B7370A6 /* Products */ = { + isa = PBXGroup; + children = ( + AE1EF0EC94DA87361C0406DA6AC248C3 /* ImagePickerSheetController.framework */, + F831E4A5EFAFD16B864480C9C0F8E1E9 /* Pods_ReactNativeCameraKit.framework */, + ); + name = Products; + sourceTree = ""; + }; + CB688DDE44D693E9312BCCFEF49508F5 /* Pods-ReactNativeCameraKit */ = { + isa = PBXGroup; + children = ( + CD097932506E41F66E1BB103B2080A8D /* Info.plist */, + 7AA7C40F5CD7AC6BF35E1B0065DA72C5 /* Pods-ReactNativeCameraKit.modulemap */, + 03E2CDD46BB9E1A4A66D0550179FDC2C /* Pods-ReactNativeCameraKit-acknowledgements.markdown */, + 9480CFCA0F9FB4526A047ED920A554BC /* Pods-ReactNativeCameraKit-acknowledgements.plist */, + 0F3AC07D2E4446CA38B0AFB55935D506 /* Pods-ReactNativeCameraKit-dummy.m */, + 68DF5BE345BF4A20C242226D8BDFC520 /* Pods-ReactNativeCameraKit-frameworks.sh */, + BA9C090317F3F76F40B0CACF691929EE /* Pods-ReactNativeCameraKit-resources.sh */, + 66B38237FA9EF751ED77E239C733829D /* Pods-ReactNativeCameraKit-umbrella.h */, + EEF467F3FE90185318D7CC581BB160FA /* Pods-ReactNativeCameraKit.debug.xcconfig */, + 3CF582E27F74A69C6F871ED64816F6DE /* Pods-ReactNativeCameraKit.release.xcconfig */, + ); + name = "Pods-ReactNativeCameraKit"; + path = "Target Support Files/Pods-ReactNativeCameraKit"; + sourceTree = ""; + }; + CF60819FDD9A8A1FDDBE8C01CFDB526F /* iOS */ = { + isa = PBXGroup; + children = ( + 9E36762FF8E4A4E113EEC970F71E699C /* Foundation.framework */, + 697E2FB9C7768EDEA1457A96EDB78BE9 /* Photos.framework */, + ); + name = iOS; + sourceTree = ""; + }; + D50700D5541FD756EDCE4782B04829C5 /* ImagePickerSheetController */ = { + isa = PBXGroup; + children = ( + A2D98780222413EDBBD45C7302EC0BA8 /* AnimationController.swift */, + 9DBA2152DC4141AF0EE54E2DB10210B5 /* ImagePickerAction.swift */, + C525DEF5158DF542A9FAB0874C83A06E /* ImagePickerSheetController.swift */, + B67719E721B448F6065B50621081684A /* PreviewCollectionView.swift */, + 75CE6E7CD62AF49861EC3F12442386C0 /* PreviewCollectionViewCell.swift */, + 2C00EDF48AC63BAA768D0A0B6E20C31B /* PreviewCollectionViewLayout.swift */, + C844465AE2EA77CFF17AA3699FFB79CD /* PreviewSupplementaryView.swift */, + FFFC468480F371982DE65A908A41DA21 /* SheetActionCollectionViewCell.swift */, + 990E4D7FD59799C10E85A6487106B18B /* SheetCollectionViewCell.swift */, + E06F339EAACD2E9ED6A6119E816DC3AA /* SheetCollectionViewLayout.swift */, + 4A35A3834BF674B5F1CDB72D9D646658 /* SheetController.swift */, + 4EBE83F6A85A4DEAE74B5AD71A974CAE /* SheetPreviewCollectionViewCell.swift */, + 9531269308E2BE6B671DDE9564BFE996 /* Resources */, + F45EBA593415998AE41C5B6B2974419A /* Support Files */, + ); + path = ImagePickerSheetController; + sourceTree = ""; + }; + EF0BF5064E61294AD74BCC8C19C17E70 /* Pods */ = { + isa = PBXGroup; + children = ( + D50700D5541FD756EDCE4782B04829C5 /* ImagePickerSheetController */, + ); + name = Pods; + sourceTree = ""; + }; + F45EBA593415998AE41C5B6B2974419A /* Support Files */ = { + isa = PBXGroup; + children = ( + CDDDD47987996CE6E4F88ACE58031BA9 /* ImagePickerSheetController.modulemap */, + 1E0275907FE8E85889145D3B97263935 /* ImagePickerSheetController.xcconfig */, + FD0EAA78B4A44CC82E24ED80A813BFDB /* ImagePickerSheetController-dummy.m */, + 12CE2841A34BEB5906032E3980F43037 /* ImagePickerSheetController-prefix.pch */, + 3134E79C0CA7BE51D6DD42575AC4BD78 /* ImagePickerSheetController-umbrella.h */, + CAE48460691A7F16DC3E2A8158DA8C1C /* Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/ImagePickerSheetController"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 5E0B6160A5A178C00ED9CD79C7BC1CD4 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 65DDC4906B56C3C19A03B2EB4257435F /* ImagePickerSheetController-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C4B1C2AFE3CA38462A9D283ED2D3A28 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CD78C10DADDEC6B5E39D47DFE8975B48 /* Pods-ReactNativeCameraKit-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 09C554F08A60A36AC2B390B2B0F706AF /* Pods-ReactNativeCameraKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = E15230A1C51A9843BED269A28D1C8D93 /* Build configuration list for PBXNativeTarget "Pods-ReactNativeCameraKit" */; + buildPhases = ( + DF3887247B7FA5F2B9570A1532E8825A /* Sources */, + 185CDE137F7E9E23F1CE9B518D47E7FB /* Frameworks */, + 9C4B1C2AFE3CA38462A9D283ED2D3A28 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + BBCF5D5AD9006C324C0CCA9B69B2FA27 /* PBXTargetDependency */, + ); + name = "Pods-ReactNativeCameraKit"; + productName = "Pods-ReactNativeCameraKit"; + productReference = F831E4A5EFAFD16B864480C9C0F8E1E9 /* Pods_ReactNativeCameraKit.framework */; + productType = "com.apple.product-type.framework"; + }; + 2AAAB9973850C35994DC04473435E1A3 /* ImagePickerSheetController */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5580ECE611FF697E03DD45816B0B5871 /* Build configuration list for PBXNativeTarget "ImagePickerSheetController" */; + buildPhases = ( + D6EFA694F15215890B83641196A85498 /* Sources */, + B00AEE85F1051CEEC27A8D13F638E23C /* Frameworks */, + 407B72996CFC6B907B5482F8FFBB4443 /* Resources */, + 5E0B6160A5A178C00ED9CD79C7BC1CD4 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ImagePickerSheetController; + productName = ImagePickerSheetController; + productReference = AE1EF0EC94DA87361C0406DA6AC248C3 /* ImagePickerSheetController.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = AF7A76083693DFBE6F6696812B7370A6 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2AAAB9973850C35994DC04473435E1A3 /* ImagePickerSheetController */, + 09C554F08A60A36AC2B390B2B0F706AF /* Pods-ReactNativeCameraKit */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 407B72996CFC6B907B5482F8FFBB4443 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9180B8BA812802D78F860175B02387FF /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D6EFA694F15215890B83641196A85498 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D0DE2F60AE2806F484AC6D0F53362A5 /* AnimationController.swift in Sources */, + 079630E2D4FDD18DA1148E24A6D9F48C /* ImagePickerAction.swift in Sources */, + E7B7BAB2FE1730965D067CE994FB7EC2 /* ImagePickerSheetController-dummy.m in Sources */, + 5A97CB0EA725BF0EA48A2B3CBF199887 /* ImagePickerSheetController.swift in Sources */, + 180378212E28F7A112A87A43DF6E5F7F /* PreviewCollectionView.swift in Sources */, + 363134533B7518E26FEB125E29D3BDF5 /* PreviewCollectionViewCell.swift in Sources */, + B8912CE08C66BD2B6189745EDB35F33F /* PreviewCollectionViewLayout.swift in Sources */, + E8129D7EC7434F22247C35916CBAD0B8 /* PreviewSupplementaryView.swift in Sources */, + 6FFF9F6BAB7E459AFFBE5C6B4343372C /* SheetActionCollectionViewCell.swift in Sources */, + EE75E9914DE58A76A5460938813EE4DC /* SheetCollectionViewCell.swift in Sources */, + 884AE123CAC9A5491C23AE729FE4832D /* SheetCollectionViewLayout.swift in Sources */, + 3343C7EF8FC7413A0A907F6FC5C78C74 /* SheetController.swift in Sources */, + F2E2DE1EC6D5DA0477EA29AF543017A2 /* SheetPreviewCollectionViewCell.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DF3887247B7FA5F2B9570A1532E8825A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3BEBBF1BC29E28E275612602AD2CBC58 /* Pods-ReactNativeCameraKit-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + BBCF5D5AD9006C324C0CCA9B69B2FA27 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ImagePickerSheetController; + target = 2AAAB9973850C35994DC04473435E1A3 /* ImagePickerSheetController */; + targetProxy = DDFBF28D1A8D92742997C008E7B80ED5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 8861DB452DF06013FA92AD2062B9FB19 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3CF582E27F74A69C6F871ED64816F6DE /* Pods-ReactNativeCameraKit.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + INFOPLIST_FILE = "Target Support Files/Pods-ReactNativeCameraKit/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_NAME = Pods_ReactNativeCameraKit; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 94547D0F14ABE31A6C5C38D3A12D793D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E0275907FE8E85889145D3B97263935 /* ImagePickerSheetController.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/ImagePickerSheetController/ImagePickerSheetController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ImagePickerSheetController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ImagePickerSheetController/ImagePickerSheetController.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = ImagePickerSheetController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A70CDAD61F90AC503C7D04CC22DA2923 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + ONLY_ACTIVE_ARCH = YES; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + CA05C723B40F3F3B1C4184E935ED6B83 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E0275907FE8E85889145D3B97263935 /* ImagePickerSheetController.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREFIX_HEADER = "Target Support Files/ImagePickerSheetController/ImagePickerSheetController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ImagePickerSheetController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ImagePickerSheetController/ImagePickerSheetController.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = ImagePickerSheetController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + F21EF67338BE2D05560FDBD505F6847C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EEF467F3FE90185318D7CC581BB160FA /* Pods-ReactNativeCameraKit.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + INFOPLIST_FILE = "Target Support Files/Pods-ReactNativeCameraKit/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_NAME = Pods_ReactNativeCameraKit; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + FB45FFD90572718D82AB9092B750F0CA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A70CDAD61F90AC503C7D04CC22DA2923 /* Debug */, + FB45FFD90572718D82AB9092B750F0CA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5580ECE611FF697E03DD45816B0B5871 /* Build configuration list for PBXNativeTarget "ImagePickerSheetController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CA05C723B40F3F3B1C4184E935ED6B83 /* Debug */, + 94547D0F14ABE31A6C5C38D3A12D793D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E15230A1C51A9843BED269A28D1C8D93 /* Build configuration list for PBXNativeTarget "Pods-ReactNativeCameraKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F21EF67338BE2D05560FDBD505F6847C /* Debug */, + 8861DB452DF06013FA92AD2062B9FB19 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-dummy.m b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-dummy.m new file mode 100644 index 0000000..aa038f5 --- /dev/null +++ b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_ImagePickerSheetController : NSObject +@end +@implementation PodsDummy_ImagePickerSheetController +@end diff --git a/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-prefix.pch b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-prefix.pch new file mode 100644 index 0000000..aa992a4 --- /dev/null +++ b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-prefix.pch @@ -0,0 +1,4 @@ +#ifdef __OBJC__ +#import +#endif + diff --git a/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-umbrella.h b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-umbrella.h new file mode 100644 index 0000000..b198a65 --- /dev/null +++ b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController-umbrella.h @@ -0,0 +1,6 @@ +#import + + +FOUNDATION_EXPORT double ImagePickerSheetControllerVersionNumber; +FOUNDATION_EXPORT const unsigned char ImagePickerSheetControllerVersionString[]; + diff --git a/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.modulemap b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.modulemap new file mode 100644 index 0000000..09a9b1b --- /dev/null +++ b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.modulemap @@ -0,0 +1,6 @@ +framework module ImagePickerSheetController { + umbrella header "ImagePickerSheetController-umbrella.h" + + export * + module * { export * } +} diff --git a/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.xcconfig b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.xcconfig new file mode 100644 index 0000000..6b6267e --- /dev/null +++ b/ios/Pods/Target Support Files/ImagePickerSheetController/ImagePickerSheetController.xcconfig @@ -0,0 +1,6 @@ +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ImagePickerSheetController" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = -framework "Photos" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_ROOT = ${SRCROOT} +SKIP_INSTALL = YES \ No newline at end of file diff --git a/ios/Pods/Target Support Files/ImagePickerSheetController/Info.plist b/ios/Pods/Target Support Files/ImagePickerSheetController/Info.plist new file mode 100644 index 0000000..8dd5fc5 --- /dev/null +++ b/ios/Pods/Target Support Files/ImagePickerSheetController/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.cocoapods.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.9.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Info.plist b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Info.plist new file mode 100644 index 0000000..6974542 --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.cocoapods.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.markdown b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.markdown new file mode 100644 index 0000000..b0c35a0 --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.markdown @@ -0,0 +1,28 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## ImagePickerSheetController + +The MIT License (MIT) + +Copyright (c) 2014 Laurin Brandner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Generated by CocoaPods - http://cocoapods.org diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.plist b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.plist new file mode 100644 index 0000000..54d0a87 --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2014 Laurin Brandner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + Title + ImagePickerSheetController + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - http://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-dummy.m b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-dummy.m new file mode 100644 index 0000000..7031172 --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_ReactNativeCameraKit : NSObject +@end +@implementation PodsDummy_Pods_ReactNativeCameraKit +@end diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-frameworks.sh b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-frameworks.sh new file mode 100755 index 0000000..8132e7e --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-frameworks.sh @@ -0,0 +1,91 @@ +#!/bin/sh +set -e + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # use filter instead of exclude so missing patterns dont' throw errors + echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" + /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current file + archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" + stripped="" + for arch in $archs; do + if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "Pods-ReactNativeCameraKit/ImagePickerSheetController.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "Pods-ReactNativeCameraKit/ImagePickerSheetController.framework" +fi diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-resources.sh b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-resources.sh new file mode 100755 index 0000000..16774fb --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-resources.sh @@ -0,0 +1,95 @@ +#!/bin/sh +set -e + +mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +realpath() { + DIRECTORY="$(cd "${1%/*}" && pwd)" + FILENAME="${1##*/}" + echo "$DIRECTORY/$FILENAME" +} + +install_resource() +{ + case $1 in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" + ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" + ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" + ;; + *.framework) + echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" + xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" + xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" + xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + /*) + echo "$1" + echo "$1" >> "$RESOURCES_TO_COPY" + ;; + *) + echo "${PODS_ROOT}/$1" + echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] +then + case "${TARGETED_DEVICE_FAMILY}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; + esac + + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "`realpath $PODS_ROOT`*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-umbrella.h b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-umbrella.h new file mode 100644 index 0000000..384665a --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-umbrella.h @@ -0,0 +1,6 @@ +#import + + +FOUNDATION_EXPORT double Pods_ReactNativeCameraKitVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_ReactNativeCameraKitVersionString[]; + diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.debug.xcconfig b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.debug.xcconfig new file mode 100644 index 0000000..95e505c --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.debug.xcconfig @@ -0,0 +1,8 @@ +EMBEDDED_CONTENT_CONTAINS_SWIFT = YES +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/ImagePickerSheetController.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ImagePickerSheetController" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-ReactNativeCameraKit +PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.modulemap b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.modulemap new file mode 100644 index 0000000..097554e --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.modulemap @@ -0,0 +1,6 @@ +framework module Pods_ReactNativeCameraKit { + umbrella header "Pods-ReactNativeCameraKit-umbrella.h" + + export * + module * { export * } +} diff --git a/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.release.xcconfig b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.release.xcconfig new file mode 100644 index 0000000..95e505c --- /dev/null +++ b/ios/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.release.xcconfig @@ -0,0 +1,8 @@ +EMBEDDED_CONTENT_CONTAINS_SWIFT = YES +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/ImagePickerSheetController.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ImagePickerSheetController" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-ReactNativeCameraKit +PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/ios/ReactNativeCameraKit-Bridging-Header.h b/ios/ReactNativeCameraKit-Bridging-Header.h new file mode 100644 index 0000000..4f813e3 --- /dev/null +++ b/ios/ReactNativeCameraKit-Bridging-Header.h @@ -0,0 +1,4 @@ +#import "RCTBridgeModule.h" +#import "AppDelegate.h" + + diff --git a/ios/ReactNativeCameraKit.m b/ios/ReactNativeCameraKit.m new file mode 100644 index 0000000..5f2d737 --- /dev/null +++ b/ios/ReactNativeCameraKit.m @@ -0,0 +1,16 @@ +// +// RCTCameraKitManager.m +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +#import "RCTBridgeModule.h" +#import "AppDelegate.h" + +@interface RCT_EXTERN_MODULE(ReactNativeCameraKit, NSObject) + +RCT_EXTERN_METHOD(presentPhotoPicker:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback) + +@end diff --git a/ios/ReactNativeCameraKit.swift b/ios/ReactNativeCameraKit.swift new file mode 100644 index 0000000..54fd139 --- /dev/null +++ b/ios/ReactNativeCameraKit.swift @@ -0,0 +1,170 @@ +// +// RCTCameraKitManager.swift +// ReactNativeCameraKit +// +// Created by Natalia Grankina on 4/13/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +import UIKit +import MobileCoreServices +import Photos +import ImagePickerSheetController + +@objc(ReactNativeCameraKit) + +class ReactNativeCameraKit: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate, CameraViewControllerDelegate { + var defaultOptions: [String: AnyObject] + var callback: RCTResponseSenderBlock? = nil + + override init() { + defaultOptions = [String: AnyObject]() + defaultOptions["takePhotoActionTitle"] = "Take a Photo" + defaultOptions["pickPhotoActionTitle"] = "Gallery" + defaultOptions["cancelActionTitle"] = "Cancel" + defaultOptions["sendSelectedPhotosTitle"] = "Send %lu Photo" + defaultOptions["aspectRatioInfoMessage"] = "Your images look best with 16:9 ratio" + defaultOptions["aspectRatios"] = ["16:9", "1:1", "4:3", "3:2", "2:3", "3:4", "9:16"] + defaultOptions["collectionName"] = "eCom" + + super.init() + } + + + func presentPhotoPicker(options: [String: AnyObject], callback: RCTResponseSenderBlock) -> Void { + var computedOptions = [String: AnyObject]() + self.callback = callback + + for (key, value) in defaultOptions { + computedOptions[key] = value + } + for (key, value) in options { + computedOptions[key] = value; + } + + dispatch_async(dispatch_get_main_queue(), { + let controller = ImagePickerSheetController(mediaType: .Image) + + let takePhotoAction = ImagePickerAction( + title: computedOptions["takePhotoActionTitle"] as! String, + handler: { _ in + self.launchCamera(["aspectRatioInfoMessage": computedOptions["aspectRatioInfoMessage"]!, "aspectRatios": computedOptions["aspectRatios"]!, "collectionName": computedOptions["collectionName"]!]) + } + ) + controller.addAction(takePhotoAction) + + let pickPhotoAction = ImagePickerAction( + title: computedOptions["pickPhotoActionTitle"] as! String, + secondaryTitle: { NSString.localizedStringWithFormat(computedOptions["sendSelectedPhotosTitle"] as! String, $0) as String}, + handler: { _ in + self.presentImagePickerController(.PhotoLibrary) + }, + secondaryHandler: { _, numberOfPhotos in + var selectedImages = [String]() + for imageAsset in controller.selectedImageAssets { + PHImageManager.defaultManager().requestImageDataForAsset(imageAsset, + options: PHImageRequestOptions(), + resultHandler: { (imageData, _, orientation, info) -> Void in + selectedImages.append(imageData!.base64EncodedStringWithOptions([])) + if (selectedImages.count == controller.selectedImageAssets.count) { + self.executeCallback(["images": selectedImages]) + } + }) + } + }) + controller.addAction(pickPhotoAction) + + let cancelAction = ImagePickerAction( + title: computedOptions["cancelActionTitle"] as! String, + style: .Cancel, + handler: { _ in + self.notifyAboutCancel() + } + ) + controller.addAction(cancelAction) + + self.presentViewControllerAnimated(controller) + }) + } + + private func presentImagePickerController(source: UIImagePickerControllerSourceType) { + dispatch_async(dispatch_get_main_queue(), { + let controller = UIImagePickerController() + controller.delegate = self + var sourceType = source + if (!UIImagePickerController.isSourceTypeAvailable(sourceType)) { + sourceType = .PhotoLibrary + } + controller.sourceType = sourceType + + controller.delegate = self + self.presentViewControllerAnimated(controller) + }) + } + + private func presentViewControllerAnimated(controller: UIViewController) { + let delegate = UIApplication.sharedApplication().delegate as? AppDelegate + delegate!.window.rootViewController!.presentViewController(controller, animated: true, completion: nil) + } + + private func hideViewControler() { + let delegate = UIApplication.sharedApplication().delegate as? AppDelegate + delegate!.window.rootViewController!.dismissViewControllerAnimated(true, completion: nil) + } + + private func executeCallback(result: [String: AnyObject]) { + if (callback != nil) { + callback!([result]) + callback = nil + } + } + + private func notifyAboutCancel() { + executeCallback(["didCancel": true]) + } + + private func launchCamera(cameraOptions: [String: AnyObject]) { + dispatch_async(dispatch_get_main_queue(), { + let cameraViewController = CameraViewController(cameraOptions: cameraOptions) + cameraViewController.cameraViewControllerDelegate = self + + let delegate = UIApplication.sharedApplication().delegate as? AppDelegate + delegate!.window.rootViewController!.presentViewController(cameraViewController, animated: true, completion: nil) + }) + } + + // UIImagePickerControllerDelegate + + func imagePickerControllerDidCancel(picker: UIImagePickerController) { + notifyAboutCancel() + hideViewControler() + } + + func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { + let mediaType = info[UIImagePickerControllerMediaType] as! NSString + if !mediaType.isEqualToString(kUTTypeImage as String) { + fatalError("Video is not supported") + } else { + let image = info[UIImagePickerControllerOriginalImage] as! UIImage + let imageData = UIImageJPEGRepresentation(image, 1.0)!.base64EncodedStringWithOptions([]) + executeCallback(["images": [imageData]]) + } + hideViewControler() + } + + // CameraViewControllerDelegate + + func imageHasBeenTaken(controller: CameraViewController, imageData: String) { + executeCallback(["images": [imageData]]) + hideViewControler() + } + + func cameraViewControllerDidCancel(controller: CameraViewController) { + hideViewControler() + } + + func onError(controller: CameraViewController, error: String) { + executeCallback(["error": [error]]) + hideViewControler() + } +} diff --git a/ios/ReactNativeCameraKit.xcodeproj/project.pbxproj b/ios/ReactNativeCameraKit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e8a2364 --- /dev/null +++ b/ios/ReactNativeCameraKit.xcodeproj/project.pbxproj @@ -0,0 +1,901 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; + 00E356F31AD99517003FC87E /* ReactNativeCameraKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ReactNativeCameraKitTests.m */; }; + 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; + 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; + 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + 8F0E60179CBB773063C32C2F /* Pods_ReactNativeCameraKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD2DB716F7216B9BD5AF69BF /* Pods_ReactNativeCameraKit.framework */; }; + D1D310CF1CBE9FD9006019A8 /* ReactNativeCameraKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310CE1CBE9FD9006019A8 /* ReactNativeCameraKit.swift */; }; + D1D310DC1CBEA062006019A8 /* ReactNativeCameraKit.m in Sources */ = {isa = PBXBuildFile; fileRef = D1D310DB1CBEA062006019A8 /* ReactNativeCameraKit.m */; }; + D1D310DF1CBEA0D0006019A8 /* CropHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310DE1CBEA0D0006019A8 /* CropHelper.swift */; }; + D1D310E21CBEA15B006019A8 /* CameraSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310E11CBEA15B006019A8 /* CameraSessionManager.swift */; }; + D1D310E41CBEA17D006019A8 /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310E31CBEA17D006019A8 /* CameraViewController.swift */; }; + D1D310E61CBEA1AA006019A8 /* CameraViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310E51CBEA1AA006019A8 /* CameraViewControllerDelegate.swift */; }; + D1D310E81CBEA1CE006019A8 /* PhotoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310E71CBEA1CE006019A8 /* PhotoViewController.swift */; }; + D1D310EA1CBEA1E6006019A8 /* PhotoViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D310E91CBEA1E6006019A8 /* PhotoViewControllerDelegate.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTActionSheet; + }; + 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTGeolocation; + }; + 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5115D1A9E6B3D00147676; + remoteInfo = RCTImage; + }; + 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B511DB1A9E6C8500147676; + remoteInfo = RCTNetwork; + }; + 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTVibration; + }; + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = ReactNativeCameraKit; + }; + 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTSettings; + }; + 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3C86DF461ADF2C930047B81A; + remoteInfo = RCTWebSocket; + }; + 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; + remoteInfo = React; + }; + 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTLinking; + }; + 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5119B1A9E6C1200147676; + remoteInfo = RCTText; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; + 00E356EE1AD99517003FC87E /* ReactNativeCameraKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactNativeCameraKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* ReactNativeCameraKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactNativeCameraKitTests.m; sourceTree = ""; }; + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* ReactNativeCameraKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactNativeCameraKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ReactNativeCameraKit/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ReactNativeCameraKit/AppDelegate.m; sourceTree = ""; }; + 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ReactNativeCameraKit/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactNativeCameraKit/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ReactNativeCameraKit/main.m; sourceTree = ""; }; + 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + A09C6955B84903CA14AEF620 /* Pods-ReactNativeCameraKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeCameraKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.debug.xcconfig"; sourceTree = ""; }; + C70242A4D4BE4A42B79CB1E5 /* Pods-ReactNativeCameraKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeCameraKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit.release.xcconfig"; sourceTree = ""; }; + CD2DB716F7216B9BD5AF69BF /* Pods_ReactNativeCameraKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReactNativeCameraKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D1D310CD1CBE9FD9006019A8 /* ReactNativeCameraKit-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactNativeCameraKit-Bridging-Header.h"; sourceTree = ""; }; + D1D310CE1CBE9FD9006019A8 /* ReactNativeCameraKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReactNativeCameraKit.swift; sourceTree = ""; }; + D1D310DB1CBEA062006019A8 /* ReactNativeCameraKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReactNativeCameraKit.m; sourceTree = ""; }; + D1D310DE1CBEA0D0006019A8 /* CropHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropHelper.swift; sourceTree = ""; }; + D1D310E11CBEA15B006019A8 /* CameraSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraSessionManager.swift; sourceTree = ""; }; + D1D310E31CBEA17D006019A8 /* CameraViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; }; + D1D310E51CBEA1AA006019A8 /* CameraViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraViewControllerDelegate.swift; sourceTree = ""; }; + D1D310E71CBEA1CE006019A8 /* PhotoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoViewController.swift; sourceTree = ""; }; + D1D310E91CBEA1E6006019A8 /* PhotoViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoViewControllerDelegate.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 146834051AC3E58100842450 /* libReact.a in Frameworks */, + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, + 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, + 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, + 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, + 8F0E60179CBB773063C32C2F /* Pods_ReactNativeCameraKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00C302A81ABCB8CE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302B61ABCB90400DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302BC1ABCB91800DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302D41ABCB9D200DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302E01ABCB9EE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, + ); + name = Products; + sourceTree = ""; + }; + 00E356EF1AD99517003FC87E /* ReactNativeCameraKitTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* ReactNativeCameraKitTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = ReactNativeCameraKitTests; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 139105B71AF99BAD00B5F7CC /* Products */ = { + isa = PBXGroup; + children = ( + 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, + ); + name = Products; + sourceTree = ""; + }; + 139FDEE71B06529A00C62182 /* Products */ = { + isa = PBXGroup; + children = ( + 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, + ); + name = Products; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* ReactNativeCameraKit */ = { + isa = PBXGroup; + children = ( + D1D310E01CBEA0F6006019A8 /* Camera */, + D1D310DD1CBEA0B4006019A8 /* Helpers */, + 008F07F21AC5B25A0029DE68 /* main.jsbundle */, + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, + 13B07FB71A68108700A75B9A /* main.m */, + D1D310CE1CBE9FD9006019A8 /* ReactNativeCameraKit.swift */, + D1D310CD1CBE9FD9006019A8 /* ReactNativeCameraKit-Bridging-Header.h */, + D1D310DB1CBEA062006019A8 /* ReactNativeCameraKit.m */, + ); + name = ReactNativeCameraKit; + sourceTree = ""; + }; + 146834001AC3E56700842450 /* Products */ = { + isa = PBXGroup; + children = ( + 146834041AC3E56700842450 /* libReact.a */, + ); + name = Products; + sourceTree = ""; + }; + 660045470EB1C3A662DB6860 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CD2DB716F7216B9BD5AF69BF /* Pods_ReactNativeCameraKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 78C398B11ACF4ADC00677621 /* Products */ = { + isa = PBXGroup; + children = ( + 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, + ); + name = Products; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + 146833FF1AC3E56700842450 /* React.xcodeproj */, + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, + ); + name = Libraries; + sourceTree = ""; + }; + 832341B11AAA6A8300B99B32 /* Products */ = { + isa = PBXGroup; + children = ( + 832341B51AAA6A8300B99B32 /* libRCTText.a */, + ); + name = Products; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* ReactNativeCameraKit */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* ReactNativeCameraKitTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + A0D5301919F082B381AED4B2 /* Pods */, + 660045470EB1C3A662DB6860 /* Frameworks */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* ReactNativeCameraKit.app */, + 00E356EE1AD99517003FC87E /* ReactNativeCameraKitTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + A0D5301919F082B381AED4B2 /* Pods */ = { + isa = PBXGroup; + children = ( + A09C6955B84903CA14AEF620 /* Pods-ReactNativeCameraKit.debug.xcconfig */, + C70242A4D4BE4A42B79CB1E5 /* Pods-ReactNativeCameraKit.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + D1D310DD1CBEA0B4006019A8 /* Helpers */ = { + isa = PBXGroup; + children = ( + D1D310DE1CBEA0D0006019A8 /* CropHelper.swift */, + ); + name = Helpers; + sourceTree = ""; + }; + D1D310E01CBEA0F6006019A8 /* Camera */ = { + isa = PBXGroup; + children = ( + D1D310E11CBEA15B006019A8 /* CameraSessionManager.swift */, + D1D310E31CBEA17D006019A8 /* CameraViewController.swift */, + D1D310E51CBEA1AA006019A8 /* CameraViewControllerDelegate.swift */, + D1D310E71CBEA1CE006019A8 /* PhotoViewController.swift */, + D1D310E91CBEA1E6006019A8 /* PhotoViewControllerDelegate.swift */, + ); + name = Camera; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* ReactNativeCameraKitTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ReactNativeCameraKitTests" */; + buildPhases = ( + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = ReactNativeCameraKitTests; + productName = ReactNativeCameraKitTests; + productReference = 00E356EE1AD99517003FC87E /* ReactNativeCameraKitTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* ReactNativeCameraKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNativeCameraKit" */; + buildPhases = ( + 75BD5BC400E0F0FFB5CA4C9D /* Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 298D3A2F8738131D7D6292FD /* Embed Pods Frameworks */, + C901BAD3B5898B500305AA85 /* Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ReactNativeCameraKit; + productName = "Hello World"; + productReference = 13B07F961A680F5B00A75B9A /* ReactNativeCameraKit.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + DevelopmentTeam = FALU6K28DC; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactNativeCameraKit" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; + ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + }, + { + ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; + ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + }, + { + ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; + ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + }, + { + ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; + ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + }, + { + ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; + ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + }, + { + ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; + ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + }, + { + ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; + ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + }, + { + ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; + ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + }, + { + ProductGroup = 139FDEE71B06529A00C62182 /* Products */; + ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + }, + { + ProductGroup = 146834001AC3E56700842450 /* Products */; + ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* ReactNativeCameraKit */, + 00E356ED1AD99517003FC87E /* ReactNativeCameraKitTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTActionSheet.a; + remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTGeolocation.a; + remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTImage.a; + remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTNetwork.a; + remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTVibration.a; + remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTSettings.a; + remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTWebSocket.a; + remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 146834041AC3E56700842450 /* libReact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libReact.a; + remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTLinking.a; + remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTText.a; + remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh"; + }; + 298D3A2F8738131D7D6292FD /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 75BD5BC400E0F0FFB5CA4C9D /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + C901BAD3B5898B500305AA85 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ReactNativeCameraKit/Pods-ReactNativeCameraKit-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* ReactNativeCameraKitTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D1D310EA1CBEA1E6006019A8 /* PhotoViewControllerDelegate.swift in Sources */, + D1D310E61CBEA1AA006019A8 /* CameraViewControllerDelegate.swift in Sources */, + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + D1D310DC1CBEA062006019A8 /* ReactNativeCameraKit.m in Sources */, + D1D310CF1CBE9FD9006019A8 /* ReactNativeCameraKit.swift in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + D1D310E81CBEA1CE006019A8 /* PhotoViewController.swift in Sources */, + D1D310E41CBEA17D006019A8 /* CameraViewController.swift in Sources */, + D1D310DF1CBEA0D0006019A8 /* CropHelper.swift in Sources */, + D1D310E21CBEA15B006019A8 /* CameraSessionManager.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* ReactNativeCameraKit */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 13B07FB21A68108700A75B9A /* Base */, + ); + name = LaunchScreen.xib; + path = ReactNativeCameraKit; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = ReactNativeCameraKitTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactNativeCameraKit.app/ReactNativeCameraKit"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = ReactNativeCameraKitTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactNativeCameraKit.app/ReactNativeCameraKit"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A09C6955B84903CA14AEF620 /* Pods-ReactNativeCameraKit.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEAD_CODE_STRIPPING = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../node_modules/react-native/React/**", + ); + INFOPLIST_FILE = ReactNativeCameraKit/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = ReactNativeCameraKit; + PRODUCT_NAME = ReactNativeCameraKit; + SWIFT_OBJC_BRIDGING_HEADER = "ReactNativeCameraKit-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C70242A4D4BE4A42B79CB1E5 /* Pods-ReactNativeCameraKit.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../node_modules/react-native/React/**", + ); + INFOPLIST_FILE = ReactNativeCameraKit/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = ReactNativeCameraKit; + PRODUCT_NAME = ReactNativeCameraKit; + SWIFT_OBJC_BRIDGING_HEADER = "ReactNativeCameraKit-Bridging-Header.h"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../node_modules/react-native/React/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../node_modules/react-native/React/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ReactNativeCameraKitTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNativeCameraKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactNativeCameraKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/ios/ReactNativeCameraKit.xcodeproj/xcshareddata/xcschemes/ReactNativeCameraKit.xcscheme b/ios/ReactNativeCameraKit.xcodeproj/xcshareddata/xcschemes/ReactNativeCameraKit.xcscheme new file mode 100644 index 0000000..5f7d181 --- /dev/null +++ b/ios/ReactNativeCameraKit.xcodeproj/xcshareddata/xcschemes/ReactNativeCameraKit.xcscheme @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/ReactNativeCameraKit.xcworkspace/contents.xcworkspacedata b/ios/ReactNativeCameraKit.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..7592e97 --- /dev/null +++ b/ios/ReactNativeCameraKit.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/ReactNativeCameraKit/AppDelegate.h b/ios/ReactNativeCameraKit/AppDelegate.h new file mode 100644 index 0000000..a9654d5 --- /dev/null +++ b/ios/ReactNativeCameraKit/AppDelegate.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface AppDelegate : UIResponder + +@property (nonatomic, strong) UIWindow *window; + +@end diff --git a/ios/ReactNativeCameraKit/AppDelegate.m b/ios/ReactNativeCameraKit/AppDelegate.m new file mode 100644 index 0000000..600f3c4 --- /dev/null +++ b/ios/ReactNativeCameraKit/AppDelegate.m @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "AppDelegate.h" + +#import "RCTRootView.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + NSURL *jsCodeLocation; + + /** + * Loading JavaScript code - uncomment the one you want. + * + * OPTION 1 + * Load from development server. Start the server from the repository root: + * + * $ npm start + * + * To run on device, change `localhost` to the IP address of your computer + * (you can get this by typing `ifconfig` into the terminal and selecting the + * `inet` value under `en0:`) and make sure your computer and iOS device are + * on the same Wi-Fi network. + */ + + //jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; + + /** + * OPTION 2 + * Load from pre-bundled file on disk. The static bundle is automatically + * generated by the "Bundle React Native code and images" build step when + * running the project on an actual device or running the project on the + * simulator in the "Release" build configuration. + */ + + jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; + + RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation + moduleName:@"ReactNativeCameraKit" + initialProperties:nil + launchOptions:launchOptions]; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [UIViewController new]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/ios/ReactNativeCameraKit/Base.lproj/LaunchScreen.xib b/ios/ReactNativeCameraKit/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..427eafd --- /dev/null +++ b/ios/ReactNativeCameraKit/Base.lproj/LaunchScreen.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/ReactNativeCameraKit/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/ReactNativeCameraKit/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..118c98f --- /dev/null +++ b/ios/ReactNativeCameraKit/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Contents.json b/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Contents.json new file mode 100644 index 0000000..7428ddc --- /dev/null +++ b/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Delete-2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Delete.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Delete-1.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete-1.png b/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete-1.png new file mode 100644 index 0000000000000000000000000000000000000000..91f7d22be01f5657db2dab7c83b2c59744949ba8 GIT binary patch literal 8101 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 Na<+H3yJEvj`5z1Z*0BHp literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete-2.png b/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete-2.png new file mode 100644 index 0000000000000000000000000000000000000000..91f7d22be01f5657db2dab7c83b2c59744949ba8 GIT binary patch literal 8101 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 Na<+H3yJEvj`5z1Z*0BHp literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete.png b/ios/ReactNativeCameraKit/Images.xcassets/CloseIcon.imageset/Delete.png new file mode 100644 index 0000000000000000000000000000000000000000..91f7d22be01f5657db2dab7c83b2c59744949ba8 GIT binary patch literal 8101 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 Na<+H3yJEvj`5z1Z*0BHp literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/Contents.json b/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/Contents.json new file mode 100644 index 0000000..58b470b --- /dev/null +++ b/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "flash_on_filled-25.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "flash_on_filled-50.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "flash_on_filled-75.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-25.png b/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-25.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0837e24d5d93ada247c41187133775fc8d7af0 GIT binary patch literal 475 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%0wnVu_`U#AOiAAEE)4(M`_JqL@;D1TB8wRq z*xrCJqg<(lDNyi-r;B5V#p$V&4E>rM1>Djb{Ztkn?mDz!<6>2rh9fRX*^Z9N>}_Rt3>cK>$i94)eSCs=?OTJQ zL-D_EP1D>eF=5|6!!RXI*?rG*KkEX+K()j*q9i4;B-JXpC>2OC7#SFv>KYp88d`=J zSX!AHTN#<@8kkra7-Sdn7NBUz%}>cptAuDUu+TLy3o$gXGBLI?F@L|Dw{lFO_K0^OdAyw!yiRkoc= zTikl%RD8opHy2^0lI_ZhB^x9z?33CzE$nyP$9L74szTqRf5pA~^s;t;`TmEj3TOML z#V7n>J<+me<);Mu!xgLo-_LJR-c`W7prNCFUFf>7o0IDVEhjsDwuzjsDJW=}Gf%yE z#gPWJ`%N8>*Y@nV7W$#6^mL=ksr~&WsyZqfzc2m%xum#dTDI_2jYYBHM-`t1N*}*v z<+e`nW}$8NQ6;O+M||%jE?vtKbevNqu)S*L)}q`KOP==@)qE||U1T@um!F9zr^sso zJ}W8Cmk0lf*Um9m{C>K?AaWm|2nK3+FoAsP|U+^_ro%e1Doe?9j^3n+W+v|%Od}9OXKGpDRNfzqi>i1^yZg)(}Z7ZG-JNqGzN=tg)VciLis~^sZkvwxl zaKeHA%Qe*O7$$G3W6`ab*9OL?YKdz^NlIc#s#S7PDv)9@GB7mNH8jvQvUftDnm{ Hr-UW|^6Uq! literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-75.png b/ios/ReactNativeCameraKit/Images.xcassets/FlashAutoIcon.imageset/flash_on_filled-75.png new file mode 100644 index 0000000000000000000000000000000000000000..71f5f82895e1a1e86876d6288ec8b99d20ee2420 GIT binary patch literal 946 zcmV;j15NyiP)002t}1ONa4l1H*(00002VoOIv0RM-N z%)bBt010qNS#tmY07w7;07w8v$!k6U00Q($L_t(&-tAgVYZFlvJ!4vnu_#z6f7?6LMR14P)Wg+C{h<15)jn3 z*M%mXOlF38_ny%~J#UkFZ{E$Bd(S;HOyUW$h$VlTz<*jJCNQTB#-f!+8LI+wdS%gyI414r)yLzIIv+ynxg{c_h=*}GWcGn2q@C6#jD<$A zD9e2FS&k>z88Tl-5#RM;t=YO3N(z{;kh0Pm!BE7Cse~|f;-Jh+6#8tvt>3y?K1Gsx zX|)_}5xY^w%E(n~3DvZ&V@J%YnU*fe7bFgKS!yk!X48=vsf&n|t)w*1@>?*46|rYL z!eq>96<6?uUBrUC5-XM>MpdV38WHA-9=lSW>r-% z45zzXl6zt|PNOIGjC07xtk$p(6~_y4No}N~(WLHX5b-F*u3o}DMNC4r9`mH$81{Fk zMa%|XAT44BdlMUI3+zQa8cE8<)#fRN`m#G&?a^LW8RZ z!J|cyx-Xh?6yz(<)p^<)N<->)ZTU-RcJ&~%E}z54<}YFdR}Vs)t$`*fuGEdR7E8!+ z^&pg@e3OpUZJpT9c6ClC?gBt{^&mP_yC(4-z$w1e8_*g=Cp>&hi%Fgi3dIy5;gFf=+a UFqD;YMgRZ+07*qoM6N<$g7<)xkN^Mx literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/Contents.json b/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/Contents.json new file mode 100644 index 0000000..26ef628 --- /dev/null +++ b/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "flash_off_filled-25.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "flash_off_filled-50.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "flash_off_filled-75.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-25.png b/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-25.png new file mode 100644 index 0000000000000000000000000000000000000000..e31c74457fd3c9080f8a0750a604bb9264a56bd3 GIT binary patch literal 541 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%0wnVu_`U#AOiAAEE)4(M`_JqL@;D1TB8wRq z*xrCJqg<(lDFXwem8Xkih{frtllFTZ4iGuEpG95z$i`^#Ry&8)9hq-eEO0F-Dhg(2 zKNwh2@R^e({=iv#iz`=;o{YV}K$lBsuE?453o|{6CeN;VSM;89|D5-8K3l%n|8QDO z{<9|==7#QDnX>t@_gq)z8IPOQKf5O&Xg-o@+BXt*SgR#gN}W`_;+GUsnFr z5PucayeL$TxxLeCF~_dFKg!6+|BTQ zl5bxbbMKMY-A{_#8)ZDL4y1de3q7&Psy0qm=KjQVAo7q~uC)>W0b9RQPj#h>SoRoA z-WWLF&G3_l!`%~R8Dff}b!QGv+qyr6`O@wA2LBj36P-T(X*l-~7__P-t`Q|Ei6yC4 z$wjF^iowXh&{WsZK-bVR#K6+Z)Y!_%OxM7~%D^DIkhcIuLvDUbW?CgggMo#vfmw*5 zft87ol?jjy(r{Nn=nPPUB*=!~{Irtt#G+J&^73-M%)IR4^e0|Vo4PZ!6Kh{JDh?Dv*&6glwGa&Pbzw+XICkDZF>6l>b17;5sexi!H@ zdc!CF4VyOy=&uaA6`}rwJ^aUFF9)4gjY)G#xq9Wg;%DzJPA^Y?cJ_{%!jEOQXU;u; zZcpvzR{wOeE`K!GdG7ocmxD)Q!8qIm}SYpSL)ABEuDk$Ch$#g*dWQMJJ z>?@DI0TUCZhhH^bIweTnx#*Lug-VglZJAz)iEC6U6(3zV>GNT`-=8T@^=nTab(v#! zeWP60jhRZK?~=`AHX3FdKI(cGCLnC=Z)10wBieA;Oiw-2l$E6_C%=5=wsrgL@W`ig zE=!@3>YeoP=ARBmW}lsliBDy^>2~Wo3q$s= zOm3Vtd8SG0`)*)mqYW(;~(EEq3h6?vI{^`+bd))HIY){$|u)!maFjkE^dl zS=n`;sjywHWNJc+i~jYQoaTn?B7Y}_mp+=CkaL7_JI_z$=!U1#^DSIHZgG#FG%Tq8~}U&Aa{7W`njxgN@xNA D6;CG# literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-75.png b/ios/ReactNativeCameraKit/Images.xcassets/FlashOffIcon.imageset/flash_off_filled-75.png new file mode 100644 index 0000000000000000000000000000000000000000..82516b3f6fb8cc3733c149d84164e2cf09baadc2 GIT binary patch literal 1108 zcmV-a1grarP)002t}1ONa4l1H*(00002VoOIv0RM-N z%)bBt010qNS#tmY6vF@j6vF`(a7{u000VJJL_t(&-tF2?NEA^V2k_r+N?B=jvyk#& zdMUa^P=ZwShfKT#og%@Ih=M}8RC=k71zoh%A`<$ab`$s5p+jOGQt1#x5D|rLLX?*C z?clmQGy7)d_kQoqx>Ub+Ti>6LGe6(V`>hF3F-CH!0smRW&nhcE)(#q{4^$%>i@4eb zd;$QpNk+$YwU*N}sw5(!iDJ51eOQPzN+jdsL7l>4JeJL%{&*ew(T0Q&RgbwWtHmbk z8UUbA1gpYl>ToA zRF2|3d~&dxO4uI!RM#D6?mRM3kgnYEkwWrk5e()6_%XBUjP9yycj{PaI$;zbeLT z=T-s(0AL6kvCX=aomvia&}5g@2*)+O6xL~XgQ!E=w}1rpoOfK|qAD<{SVR{#i3;9& z+*BV7SV#x<4Rzdm!|T==vKSZU;4nXrIh~q3sV;@FQeB5N5_x-~VS{?L3{I!9NEYw| z`$J%pDAz%O^-NqvCunVGkF!)kv(!vO%4g*aZKt=IPhP#>LfJNj-b$@h*ZWHhZ>K|Z ztV1%V4OS{N`MV^gPIJ^6R{_@=%$#+Uv0Z4x%vtwY`&hUAeJiY$=Dk-e!s<+5rmVdI z+v}5TkEk+KEUX(!)ElgJ^%1~KS??97Y1H_7aZ8<+Slbk+c^p*q)P$L_Iuxu60e!W~ z>1M3_SDvRKOKQMOP*r)TaZjonz)V;teW)}xM~-2Bmt?{k@}>GA)+iQCjw;8jhjo!X zG6xI%zEaLQ;z12)J@X=Aa@IW;YC`v2-34p6$trObbknF6%&-Vc*<>|jQ4Sh~b0pD@ z6n5KWUC**a@9I%aI`CZvrFkrkm$fB>Vpm{vo2=5jHFGR&rWw)r$S4twdO;tFs8#!{ z%ntnm_(GIYg685v$yqVSKl(3=e;4ZyRNR<}NRA+30000bbVXQnWMOn=I%9HWVRU5x zGB7bUEio`HF*#H)IXX2nIx;aWFf=+aFs{}!{r~^~C3HntbYx+4WjbwdWNBu305UK! zH7zhWEig7zF)%tbGCDLlEig1XFfe;p8F&By02y>eSaefwW^{L9a%BK_cXuvnZfkR6 aVQ^(GZ*pgw?mQX*0000T+`_oVy81n{*WXpD9};=5Nv{9cP$wbp`_J#@MyA&{_|!YE7a!#Q zWx4&_(#=54oCO|{#S9E=Z$Ow)uGGR5C^*H_#W6(VeD8(pLQMuDEf16RJNC9W+}Qo@ z_x?HR=7I%t6Z7|T);D?F4E^W0HSGC?jBOTMtX~9iR5^Go<>zVRaZ64(lwiedpuQnO zE5Y?uHoMxTn-=O~b!sOMsePT0w|T;h_Y*a~uf4JBz`28VKlUDZxT3&na&`N(d14}DYV=E&wT>}#<1B2{B-U1X2x%nxXX_XKS1{S&oW+8?KRwl+) zCZ-S#!KM;MKn;>08-nxGO3D+9QW?t2%k?tzvWt@w3sUv+i_&MmvylQSV(@hJb6Mw< G&;$S;M)>*w literal 0 HcmV?d00001 diff --git a/ios/ReactNativeCameraKit/Images.xcassets/FlashOnIcon.imageset/flash_on_filled-50.png b/ios/ReactNativeCameraKit/Images.xcassets/FlashOnIcon.imageset/flash_on_filled-50.png new file mode 100644 index 0000000000000000000000000000000000000000..acafd2a0451a67c85877fac7af79dc9ddfb368b2 GIT binary patch literal 812 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 + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/ReactNativeCameraKit/main.m b/ios/ReactNativeCameraKit/main.m new file mode 100644 index 0000000..3d767fc --- /dev/null +++ b/ios/ReactNativeCameraKit/main.m @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/ios/ReactNativeCameraKitTests/Info.plist b/ios/ReactNativeCameraKitTests/Info.plist new file mode 100644 index 0000000..886825c --- /dev/null +++ b/ios/ReactNativeCameraKitTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/ios/ReactNativeCameraKitTests/ReactNativeCameraKitTests.m b/ios/ReactNativeCameraKitTests/ReactNativeCameraKitTests.m new file mode 100644 index 0000000..1b95c9f --- /dev/null +++ b/ios/ReactNativeCameraKitTests/ReactNativeCameraKitTests.m @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import +#import + +#import "RCTLog.h" +#import "RCTRootView.h" + +#define TIMEOUT_SECONDS 240 +#define TEXT_TO_LOOK_FOR @"Welcome to React Native!" + +@interface ReactNativeCameraKitTests : XCTestCase + +@end + +@implementation ReactNativeCameraKitTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; + RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + + RCTSetLogFunction(RCTDefaultLogFunction); + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + + +@end diff --git a/package.json b/package.json new file mode 100644 index 0000000..bf5e4e9 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "react-native-camera-kit", + "version": "0.0.1", + "private": true, + "scripts": { + "start": "node node_modules/react-native/local-cli/cli.js start" + }, + "dependencies": { + "react": "^0.14.8", + "react-native": "^0.23.1" + } +}