Feature/refactor (#1)

* Refactor types

* Refactor messages

* Add image preview

* Use Context API

* Update dependencies

* Add tests
This commit is contained in:
Alex
2020-08-09 18:36:59 +02:00
committed by GitHub
parent 6a405b3b5c
commit ebe98809b9
42 changed files with 2466 additions and 2309 deletions

View File

@@ -20,7 +20,7 @@ import com.android.build.OutputFile
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
* // https://reactnative.dev/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // whether to bundle JS and assets in debug mode
@@ -78,7 +78,7 @@ import com.android.build.OutputFile
*/
project.ext.react = [
enableHermes: false, // clean and rebuild if changing
enableHermes: false, // clean and rebuild if changing
]
apply from: "../../node_modules/react-native/react.gradle"
@@ -157,20 +157,13 @@ android {
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
packagingOptions {
pickFirst "lib/armeabi-v7a/libc++_shared.so"
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/x86/libc++_shared.so"
pickFirst "lib/x86_64/libc++_shared.so"
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
@@ -192,19 +185,20 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
exclude group: 'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group: 'com.facebook.flipper'
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group: 'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";

View File

@@ -12,7 +12,7 @@ buildscript {
jcenter()
}
dependencies {
classpath('com.android.tools.build:gradle:3.6.2')
classpath('com.android.tools.build:gradle:4.0.1')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -25,4 +25,4 @@ android.useAndroidX=true
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.37.0
FLIPPER_VERSION=0.39.0

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $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" ;;
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
@@ -175,14 +175,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@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="-Xmx64m" "-Xms64m"

View File

@@ -1,90 +1,18 @@
platform :ios, '9.0'
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
def add_flipper_pods!(versions = {})
versions['Flipper'] ||= '~> 0.37.0'
versions['DoubleConversion'] ||= '1.1.7'
versions['Flipper-Folly'] ||= '~> 2.2'
versions['Flipper-Glog'] ||= '0.3.6'
versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
versions['Flipper-RSocket'] ||= '~> 1.1'
pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutComponentKitSupport', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'
# List all transitive dependencies for FlipperKit pods
# to avoid them being linked in Release builds
pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
end
# Post Install processing for Flipper
def flipper_post_install(installer)
installer.pods_project.targets.each do |target|
if target.name == 'YogaKit'
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '4.1'
end
end
end
end
platform :ios, '10.0'
target 'example' do
# Pods for example
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/'
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
config = use_native_modules!
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
use_native_modules!
use_react_native!(:path => config["reactNativePath"])
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
add_flipper_pods!
use_flipper!
post_install do |installer|
flipper_post_install(installer)
end

View File

@@ -2,19 +2,16 @@ PODS:
- boost-for-react-native (1.63.0)
- CocoaAsyncSocket (7.6.4)
- CocoaLibEvent (1.0.0)
- ComponentKit (0.30):
- RenderCore (= 0.30)
- Yoga (~> 1.14)
- DoubleConversion (1.1.6)
- FBLazyVector (0.62.2)
- FBReactNativeSpec (0.62.2):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.62.2)
- RCTTypeSafety (= 0.62.2)
- React-Core (= 0.62.2)
- React-jsi (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- Flipper (0.37.0):
- FBLazyVector (0.63.2)
- FBReactNativeSpec (0.63.2):
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.2)
- RCTTypeSafety (= 0.63.2)
- React-Core (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- Flipper (0.41.5):
- Flipper-Folly (~> 2.2)
- Flipper-RSocket (~> 1.1)
- Flipper-DoubleConversion (1.1.7)
@@ -28,50 +25,44 @@ PODS:
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.1.0):
- Flipper-Folly (~> 2.2)
- FlipperKit (0.37.0):
- FlipperKit/Core (= 0.37.0)
- FlipperKit/Core (0.37.0):
- Flipper (~> 0.37.0)
- FlipperKit (0.41.5):
- FlipperKit/Core (= 0.41.5)
- FlipperKit/Core (0.41.5):
- Flipper (~> 0.41.5)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- FlipperKit/CppBridge (0.37.0):
- Flipper (~> 0.37.0)
- FlipperKit/FBCxxFollyDynamicConvert (0.37.0):
- FlipperKit/CppBridge (0.41.5):
- Flipper (~> 0.41.5)
- FlipperKit/FBCxxFollyDynamicConvert (0.41.5):
- Flipper-Folly (~> 2.2)
- FlipperKit/FBDefines (0.37.0)
- FlipperKit/FKPortForwarding (0.37.0):
- FlipperKit/FBDefines (0.41.5)
- FlipperKit/FKPortForwarding (0.41.5):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.37.0)
- FlipperKit/FlipperKitLayoutComponentKitSupport (0.37.0):
- ComponentKit (~> 0.0)
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutPlugin
- FlipperKit/FlipperKitLayoutTextSearchable
- FlipperKit/FlipperKitLayoutPlugin (0.37.0):
- FlipperKit/FlipperKitHighlightOverlay (0.41.5)
- FlipperKit/FlipperKitLayoutPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.37.0)
- FlipperKit/FlipperKitNetworkPlugin (0.37.0):
- FlipperKit/FlipperKitLayoutTextSearchable (0.41.5)
- FlipperKit/FlipperKitNetworkPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.37.0):
- FlipperKit/FlipperKitReactPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.37.0):
- FlipperKit/FlipperKitUserDefaultsPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.37.0):
- FlipperKit/SKIOSNetworkPlugin (0.41.5):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Folly (2018.10.22.00):
- Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- Folly/Default (= 2018.10.22.00)
- Folly/Default (= 2020.01.13.00)
- glog
- Folly/Default (2018.10.22.00):
- Folly/Default (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- glog
@@ -79,231 +70,236 @@ PODS:
- OpenSSL-Universal (1.0.2.19):
- OpenSSL-Universal/Static (= 1.0.2.19)
- OpenSSL-Universal/Static (1.0.2.19)
- RCTRequired (0.62.2)
- RCTTypeSafety (0.62.2):
- FBLazyVector (= 0.62.2)
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.62.2)
- React-Core (= 0.62.2)
- React (0.62.2):
- React-Core (= 0.62.2)
- React-Core/DevSupport (= 0.62.2)
- React-Core/RCTWebSocket (= 0.62.2)
- React-RCTActionSheet (= 0.62.2)
- React-RCTAnimation (= 0.62.2)
- React-RCTBlob (= 0.62.2)
- React-RCTImage (= 0.62.2)
- React-RCTLinking (= 0.62.2)
- React-RCTNetwork (= 0.62.2)
- React-RCTSettings (= 0.62.2)
- React-RCTText (= 0.62.2)
- React-RCTVibration (= 0.62.2)
- React-Core (0.62.2):
- Folly (= 2018.10.22.00)
- RCTRequired (0.63.2)
- RCTTypeSafety (0.63.2):
- FBLazyVector (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.2)
- React-Core (= 0.63.2)
- React (0.63.2):
- React-Core (= 0.63.2)
- React-Core/DevSupport (= 0.63.2)
- React-Core/RCTWebSocket (= 0.63.2)
- React-RCTActionSheet (= 0.63.2)
- React-RCTAnimation (= 0.63.2)
- React-RCTBlob (= 0.63.2)
- React-RCTImage (= 0.63.2)
- React-RCTLinking (= 0.63.2)
- React-RCTNetwork (= 0.63.2)
- React-RCTSettings (= 0.63.2)
- React-RCTText (= 0.63.2)
- React-RCTVibration (= 0.63.2)
- React-callinvoker (0.63.2)
- React-Core (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.62.2)
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-Core/Default (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/CoreModulesHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/CoreModulesHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/Default (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/Default (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/DevSupport (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/DevSupport (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.62.2)
- React-Core/RCTWebSocket (= 0.62.2)
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-jsinspector (= 0.62.2)
- React-Core/Default (= 0.63.2)
- React-Core/RCTWebSocket (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- React-jsinspector (= 0.63.2)
- Yoga
- React-Core/RCTActionSheetHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTActionSheetHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTAnimationHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTAnimationHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTBlobHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTBlobHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTImageHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTImageHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTLinkingHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTLinkingHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTNetworkHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTNetworkHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTSettingsHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTSettingsHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTTextHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTTextHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTVibrationHeaders (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTVibrationHeaders (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-Core/RCTWebSocket (0.62.2):
- Folly (= 2018.10.22.00)
- React-Core/RCTWebSocket (0.63.2):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.62.2)
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsiexecutor (= 0.62.2)
- React-Core/Default (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsiexecutor (= 0.63.2)
- Yoga
- React-CoreModules (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.62.2)
- React-Core/CoreModulesHeaders (= 0.62.2)
- React-RCTImage (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-cxxreact (0.62.2):
- React-CoreModules (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/CoreModulesHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- React-RCTImage (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-cxxreact (0.63.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsinspector (= 0.62.2)
- React-jsi (0.62.2):
- React-callinvoker (= 0.63.2)
- React-jsinspector (= 0.63.2)
- React-jsi (0.63.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsi/Default (= 0.62.2)
- React-jsi/Default (0.62.2):
- React-jsi/Default (= 0.63.2)
- React-jsi/Default (0.63.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsiexecutor (0.62.2):
- React-jsiexecutor (0.63.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsinspector (0.62.2)
- react-native-safe-area-context (3.0.7):
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- React-jsinspector (0.63.2)
- react-native-image-picker (2.3.3):
- React
- React-RCTActionSheet (0.62.2):
- React-Core/RCTActionSheetHeaders (= 0.62.2)
- React-RCTAnimation (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.62.2)
- React-Core/RCTAnimationHeaders (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-RCTBlob (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- React-Core/RCTBlobHeaders (= 0.62.2)
- React-Core/RCTWebSocket (= 0.62.2)
- React-jsi (= 0.62.2)
- React-RCTNetwork (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-RCTImage (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.62.2)
- React-Core/RCTImageHeaders (= 0.62.2)
- React-RCTNetwork (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-RCTLinking (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- React-Core/RCTLinkingHeaders (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-RCTNetwork (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.62.2)
- React-Core/RCTNetworkHeaders (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-RCTSettings (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.62.2)
- React-Core/RCTSettingsHeaders (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- React-RCTText (0.62.2):
- React-Core/RCTTextHeaders (= 0.62.2)
- React-RCTVibration (0.62.2):
- FBReactNativeSpec (= 0.62.2)
- Folly (= 2018.10.22.00)
- React-Core/RCTVibrationHeaders (= 0.62.2)
- ReactCommon/turbomodule/core (= 0.62.2)
- ReactCommon/callinvoker (0.62.2):
- react-native-safe-area-context (3.1.4):
- React
- React-RCTActionSheet (0.63.2):
- React-Core/RCTActionSheetHeaders (= 0.63.2)
- React-RCTAnimation (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTAnimationHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTBlob (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.63.2)
- React-Core/RCTWebSocket (= 0.63.2)
- React-jsi (= 0.63.2)
- React-RCTNetwork (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTImage (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTImageHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- React-RCTNetwork (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTLinking (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- React-Core/RCTLinkingHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTNetwork (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTNetworkHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTSettings (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.2)
- React-Core/RCTSettingsHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- React-RCTText (0.63.2):
- React-Core/RCTTextHeaders (= 0.63.2)
- React-RCTVibration (0.63.2):
- FBReactNativeSpec (= 0.63.2)
- Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.63.2)
- React-jsi (= 0.63.2)
- ReactCommon/turbomodule/core (= 0.63.2)
- ReactCommon/turbomodule/core (0.63.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.62.2)
- ReactCommon/turbomodule/core (0.62.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.62.2)
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- ReactCommon/callinvoker (= 0.62.2)
- RenderCore (0.30)
- React-callinvoker (= 0.63.2)
- React-Core (= 0.63.2)
- React-cxxreact (= 0.63.2)
- React-jsi (= 0.63.2)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
@@ -312,31 +308,31 @@ DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Flipper (~> 0.37.0)
- Flipper (~> 0.41.1)
- Flipper-DoubleConversion (= 1.1.7)
- Flipper-Folly (~> 2.2)
- Flipper-Glog (= 0.3.6)
- Flipper-PeerTalk (~> 0.0.4)
- Flipper-RSocket (~> 1.1)
- FlipperKit (~> 0.37.0)
- FlipperKit/Core (~> 0.37.0)
- FlipperKit/CppBridge (~> 0.37.0)
- FlipperKit/FBCxxFollyDynamicConvert (~> 0.37.0)
- FlipperKit/FBDefines (~> 0.37.0)
- FlipperKit/FKPortForwarding (~> 0.37.0)
- FlipperKit/FlipperKitHighlightOverlay (~> 0.37.0)
- FlipperKit/FlipperKitLayoutComponentKitSupport (~> 0.37.0)
- FlipperKit/FlipperKitLayoutPlugin (~> 0.37.0)
- FlipperKit/FlipperKitLayoutTextSearchable (~> 0.37.0)
- FlipperKit/FlipperKitNetworkPlugin (~> 0.37.0)
- FlipperKit/FlipperKitReactPlugin (~> 0.37.0)
- FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.37.0)
- FlipperKit/SKIOSNetworkPlugin (~> 0.37.0)
- FlipperKit (~> 0.41.1)
- FlipperKit/Core (~> 0.41.1)
- FlipperKit/CppBridge (~> 0.41.1)
- FlipperKit/FBCxxFollyDynamicConvert (~> 0.41.1)
- FlipperKit/FBDefines (~> 0.41.1)
- FlipperKit/FKPortForwarding (~> 0.41.1)
- FlipperKit/FlipperKitHighlightOverlay (~> 0.41.1)
- FlipperKit/FlipperKitLayoutPlugin (~> 0.41.1)
- FlipperKit/FlipperKitLayoutTextSearchable (~> 0.41.1)
- FlipperKit/FlipperKitNetworkPlugin (~> 0.41.1)
- FlipperKit/FlipperKitReactPlugin (~> 0.41.1)
- FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.41.1)
- FlipperKit/SKIOSNetworkPlugin (~> 0.41.1)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
@@ -345,6 +341,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
@@ -355,7 +352,6 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -364,7 +360,6 @@ SPEC REPOS:
- boost-for-react-native
- CocoaAsyncSocket
- CocoaLibEvent
- ComponentKit
- Flipper
- Flipper-DoubleConversion
- Flipper-Folly
@@ -373,7 +368,6 @@ SPEC REPOS:
- Flipper-RSocket
- FlipperKit
- OpenSSL-Universal
- RenderCore
- YogaKit
EXTERNAL SOURCES:
@@ -393,6 +387,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
React-callinvoker:
:path: "../node_modules/react-native/ReactCommon/callinvoker"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
@@ -405,6 +401,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-image-picker:
:path: "../node_modules/react-native-image-picker"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
React-RCTActionSheet:
@@ -434,44 +432,44 @@ SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
ComponentKit: c34da1ab3515cf18db68a4ba22c6599568d1de74
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: 4aab18c93cd9546e4bfed752b4084585eca8b245
FBReactNativeSpec: 5465d51ccfeecb7faa12f9ae0024f2044ce4044e
Flipper: 1670db365568191bd123a0c905b834e77ba9e3d3
DoubleConversion: cde416483dac037923206447da6e1454df403714
FBLazyVector: 3ef4a7f62e7db01092f9d517d2ebc0d0677c4a37
FBReactNativeSpec: dc7fa9088f0f2a998503a352b0554d69a4391c5a
Flipper: 33585e2d9810fe5528346be33bcf71b37bb7ae13
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
FlipperKit: afd4259ef9eadeeb2d30250b37d95cb3b6b97a69
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
FlipperKit: bc68102cd4952a258a23c9c1b316c7bec1fecf83
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
RCTRequired: cec6a34b3ac8a9915c37e7e4ad3aa74726ce4035
RCTTypeSafety: 93006131180074cffa227a1075802c89a49dd4ce
React: 29a8b1a02bd764fb7644ef04019270849b9a7ac3
React-Core: b12bffb3f567fdf99510acb716ef1abd426e0e05
React-CoreModules: 4a9b87bbe669d6c3173c0132c3328e3b000783d0
React-cxxreact: e65f9c2ba0ac5be946f53548c1aaaee5873a8103
React-jsi: b6dc94a6a12ff98e8877287a0b7620d365201161
React-jsiexecutor: 1540d1c01bb493ae3124ed83351b1b6a155db7da
React-jsinspector: 512e560d0e985d0e8c479a54a4e5c147a9c83493
react-native-safe-area-context: ef6f16c66b0797ecae1bf86c103dfb3dc16fc33d
React-RCTActionSheet: f41ea8a811aac770e0cc6e0ad6b270c644ea8b7c
React-RCTAnimation: 49ab98b1c1ff4445148b72a3d61554138565bad0
React-RCTBlob: a332773f0ebc413a0ce85942a55b064471587a71
React-RCTImage: e70be9b9c74fe4e42d0005f42cace7981c994ac3
React-RCTLinking: c1b9739a88d56ecbec23b7f63650e44672ab2ad2
React-RCTNetwork: 73138b6f45e5a2768ad93f3d57873c2a18d14b44
React-RCTSettings: 6e3738a87e21b39a8cb08d627e68c44acf1e325a
React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d
React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256
ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3
RenderCore: d779c47622b313ce2d51bb36d084517af38b0dc1
Yoga: 3ebccbdd559724312790e7742142d062476b698e
RCTRequired: f13f25e7b12f925f1f6a6a8c69d929a03c0129fe
RCTTypeSafety: 44982c5c8e43ff4141eb519a8ddc88059acd1f3a
React: e1c65dd41cb9db13b99f24608e47dd595f28ca9a
React-callinvoker: 552a6a6bc8b3bb794cf108ad59e5a9e2e3b4fc98
React-Core: 9d341e725dc9cd2f49e4c49ad1fc4e8776aa2639
React-CoreModules: 5335e168165da7f7083ce7147768d36d3e292318
React-cxxreact: d3261ec5f7d11743fbf21e263a34ea51d1f13ebc
React-jsi: 54245e1d5f4b690dec614a73a3795964eeef13a8
React-jsiexecutor: 8ca588cc921e70590820ce72b8789b02c67cce38
React-jsinspector: b14e62ebe7a66e9231e9581279909f2fc3db6606
react-native-image-picker: 3d3f85baabca60a00b75fb8facc1376db7bbdafa
react-native-safe-area-context: eb91fe1fb3f7b87d9c30a7f0808407d8569d539d
React-RCTActionSheet: 910163b6b09685a35c4ebbc52b66d1bfbbe39fc5
React-RCTAnimation: 9a883bbe1e9d2e158d4fb53765ed64c8dc2200c6
React-RCTBlob: 39cf0ece1927996c4466510e25d2105f67010e13
React-RCTImage: de355d738727b09ad3692f2a979affbd54b5f378
React-RCTLinking: 8122f221d395a63364b2c0078ce284214bd04575
React-RCTNetwork: 8f96c7b49ea6a0f28f98258f347b6ad218bc0830
React-RCTSettings: 8a49622aff9c1925f5455fa340b6fe4853d64ab6
React-RCTText: 1b6773e776e4b33f90468c20fe3b16ca3e224bb8
React-RCTVibration: 4d2e726957f4087449739b595f107c0d4b6c2d2d
ReactCommon: a0a1edbebcac5e91338371b72ffc66aa822792ce
Yoga: 7740b94929bbacbddda59bf115b5317e9a161598
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: acbd6610b7831a74207daab8c8f1f3a49b537e00
PODFILE CHECKSUM: 92b8aaa3885dd8bbc49d40800e635370282f63b6
COCOAPODS: 1.9.3

View File

@@ -112,6 +112,7 @@
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
DA902D70F8ECC07833B03010 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -203,6 +204,24 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
DA902D70F8ECC07833B03010 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
FD10A7F022414F080027D42C /* Start Packager */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -244,10 +263,6 @@
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"FB_SONARKIT_ENABLED=1",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_ROOT}/Headers/Public\"",
@@ -375,7 +390,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "-D DEBUG";
@@ -423,7 +438,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;

View File

@@ -16,9 +16,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, RCTBridgeDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
#if DEBUG
initializeFlipper(with: application)
#endif
let bridge = RCTBridge(delegate: self, launchOptions: launchOptions)
let rootView = RCTRootView(bridge: bridge!, moduleName: "example", initialProperties: nil)
@@ -42,16 +40,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate, RCTBridgeDelegate {
#endif
}
#if DEBUG
private func initializeFlipper(with application: UIApplication) {
#if DEBUG
let client = FlipperClient.shared()
let layoutDescriptionMapper = SKDescriptorMapper(defaults: ())
FlipperKitLayoutComponentKitSupport.setUpWith(layoutDescriptionMapper)
client?.add(FlipperKitLayoutPlugin(rootNode: application, with: layoutDescriptionMapper))
client?.add(FKUserDefaultsPlugin(suiteName: nil))
client?.add(FlipperKitReactPlugin())
client?.add(FlipperKitNetworkPlugin(networkAdapter: SKIOSNetworkAdapter()))
client?.start()
#endif
}
#endif
}

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -15,8 +16,8 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Copyright © 2020 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
<rect key="frame" x="0.0" y="626.5" width="375" height="20.5"/>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
<rect key="frame" x="0.0" y="647" width="375" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@@ -27,22 +28,31 @@
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="MN2-I3-ftu">
<rect key="frame" x="0.0" y="626" width="375" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" secondItem="MN2-I3-ftu" secondAttribute="bottom" constant="20" id="OZV-Vh-mqD"/>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="SfN-ll-jLj"/>
<constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
<constraint firstItem="MN2-I3-ftu" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="akx-eg-2ui"/>
<constraint firstItem="MN2-I3-ftu" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" id="i1E-0Y-4RG"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="x7j-FC-K8j"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
<point key="canvasLocation" x="52.173913043478265" y="375"/>
</scene>
</scenes>
</document>
</document>

View File

@@ -14,26 +14,27 @@
},
"dependencies": {
"react": "^16.13.1",
"react-native": "^0.62.2",
"react-native-safe-area-context": "^3.0.7"
"react-native": "^0.63.2",
"react-native-image-picker": "^2.3.3",
"react-native-safe-area-context": "^3.1.4"
},
"devDependencies": {
"@babel/core": "^7.10.3",
"@babel/runtime": "^7.10.3",
"@babel/core": "^7.11.1",
"@babel/runtime": "^7.11.2",
"@react-native-community/eslint-config": "^2.0.0",
"@types/jest": "^26.0.3",
"@types/react-native": "^0.62.14",
"@types/react-test-renderer": "^16.9.2",
"@types/uuid": "^8.0.0",
"babel-jest": "^26.1.0",
"@types/jest": "^26.0.9",
"@types/react-native": "^0.63.6",
"@types/react-test-renderer": "^16.9.3",
"@types/uuid": "^8.0.1",
"babel-jest": "^26.2.2",
"casual": "^1.6.2",
"eslint": "^7.3.1",
"eslint": "^7.6.0",
"eslint-plugin-simple-import-sort": "^5.0.3",
"jest": "^26.1.0",
"metro-react-native-babel-preset": "^0.59.0",
"jest": "^26.2.2",
"metro-react-native-babel-preset": "^0.61.0",
"react-test-renderer": "^16.13.1",
"typescript": "^3.9.5",
"uuid": "^8.2.0"
"typescript": "^3.9.7",
"uuid": "^8.3.0"
},
"jest": {
"preset": "react-native",

View File

@@ -23,6 +23,7 @@ const messages = [...Array(numberOfMessages)].map((_, index) => {
id: uuidv4(),
text,
timestamp,
type: 'text',
}
return data
})

View File

@@ -1,19 +1,46 @@
import { Chat, Message } from '@flyerhq/react-native-chat-ui'
import {
Chat,
MessageType,
SendImageCallback,
} from '@flyerhq/react-native-chat-ui'
import React, { useState } from 'react'
import { StatusBar } from 'react-native'
import ImagePicker from 'react-native-image-picker'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import data from './messages.json'
import users from './users.json'
const App = () => {
const [messages, setMessages] = useState<Message[]>(data)
const [messages, setMessages] = useState(data as MessageType.Any[])
const handleSendPress = (message: Message) => {
const handleAttachmentPress = (send: SendImageCallback) => {
ImagePicker.showImagePicker(
{ maxWidth: 1440, quality: 0.7 },
(response) => {
if (response.data) {
send({
height: response.height,
imageUrl: 'data:image/jpeg;base64,' + response.data,
width: response.width,
})
}
}
)
}
const handleSendPress = (message: MessageType.Any) => {
setMessages([message, ...messages])
}
return (
<SafeAreaProvider>
<Chat messages={messages} onSendPress={handleSendPress} user={users[0]} />
<StatusBar barStyle='dark-content' />
<Chat
messages={messages}
onAttachmentPress={handleAttachmentPress}
onSendPress={handleSendPress}
user={users[0]}
/>
</SafeAreaProvider>
)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,13 @@
import { Message, Size, User } from '../src/types'
import { MessageType, Size, User } from '../src/types'
export const message: Message = {
export const imageMessage: MessageType.Image = {
authorId: 'userId',
height: 100,
id: 'uuidv4',
text: 'text',
imageUrl: 'https://avatars1.githubusercontent.com/u/59206044',
timestamp: 0,
type: 'image',
width: 100,
}
export const size: Size = {
@@ -12,6 +15,14 @@ export const size: Size = {
width: 414,
}
export const textMessage: MessageType.Text = {
authorId: 'userId',
id: 'uuidv4',
text: 'text',
timestamp: 0,
type: 'text',
}
export const user: User = {
id: 'userId',
name: 'Alex',

View File

@@ -21,29 +21,30 @@
"type-coverage": "type-coverage --is 100 --strict --ignore-catch --cache"
},
"dependencies": {
"@flyerhq/react-native-keyboard-accessory-view": "^1.2.0"
"@flyerhq/react-native-keyboard-accessory-view": "^1.3.0",
"react-native-image-viewing": "^0.2.0"
},
"devDependencies": {
"@babel/core": "^7.10.3",
"@babel/runtime": "^7.10.3",
"@babel/core": "^7.11.1",
"@babel/runtime": "^7.11.2",
"@react-native-community/eslint-config": "^2.0.0",
"@types/jest": "^26.0.3",
"@types/react-native": "^0.62.14",
"@types/react-test-renderer": "^16.9.2",
"babel-jest": "^26.1.0",
"@testing-library/react-native": "^7.0.1",
"@types/jest": "^26.0.9",
"@types/react-native": "^0.63.6",
"@types/react-test-renderer": "^16.9.3",
"babel-jest": "^26.2.2",
"copyfiles": "^2.3.0",
"eslint": "^7.3.1",
"eslint-plugin-jest": "^23.17.1",
"eslint": "^7.6.0",
"eslint-plugin-jest": "^23.20.0",
"eslint-plugin-simple-import-sort": "^5.0.3",
"jest": "^26.1.0",
"metro-react-native-babel-preset": "^0.59.0",
"jest": "^26.2.2",
"metro-react-native-babel-preset": "^0.61.0",
"react": "^16.13.1",
"react-native": "^0.62.2",
"react-native-safe-area-context": "^3.0.7",
"react-native-testing-library": "^2.1.0",
"react-native": "^0.63.2",
"react-native-safe-area-context": "^3.1.4",
"react-test-renderer": "^16.13.1",
"type-coverage": "^2.8.2",
"typescript": "^3.9.5"
"type-coverage": "^2.9.0",
"typescript": "^3.9.7"
},
"peerDependencies": {
"react": "*",

View File

@@ -7,13 +7,11 @@ import {
} from 'react-native'
export interface AttachmentButtonProps {
disabled?: boolean
onPress?: () => void
touchableOpacityProps?: TouchableOpacityProps
}
export const AttachmentButton = ({
disabled,
onPress,
touchableOpacityProps,
}: AttachmentButtonProps) => {
@@ -26,8 +24,6 @@ export const AttachmentButton = ({
<TouchableOpacity
accessibilityRole='button'
accessibilityLabel='Add an attachment'
accessibilityState={{ disabled }}
disabled={disabled}
{...touchableOpacityProps}
onPress={handlePress}
>

View File

@@ -1,14 +0,0 @@
import * as React from 'react'
import { fireEvent, render } from 'react-native-testing-library'
import { AttachmentButton } from '../AttachmentButton'
describe('attachment button', () => {
it('sends an event', () => {
expect.assertions(1)
const onPress = jest.fn()
const { getByA11yLabel } = render(<AttachmentButton onPress={onPress} />)
const button = getByA11yLabel('Add an attachment')
fireEvent.press(button)
expect(onPress).toHaveBeenCalledWith()
})
})

View File

@@ -3,14 +3,16 @@ import {
usePanResponder,
} from '@flyerhq/react-native-keyboard-accessory-view'
import * as React from 'react'
import { FlatList, SafeAreaView } from 'react-native'
import { Message, User } from '../../types'
import { FlatList, SafeAreaView, StatusBar, View } from 'react-native'
import ImageView from 'react-native-image-viewing'
import { MessageType, User } from '../../types'
import { UserContext } from '../../utils'
import { Input, InputProps } from '../Input'
import { TextMessage } from '../TextMessage'
import { Message } from '../Message'
import styles from './styles'
export interface ChatProps extends InputProps {
messages: Message[]
messages: MessageType.Any[]
user: User
}
@@ -18,15 +20,22 @@ export const Chat = ({
messages,
onAttachmentPress,
onSendPress,
textInputProps,
user,
}: ChatProps) => {
const { onLayout, size } = useComponentSize()
const { panHandlers, positionY } = usePanResponder()
const [contentBottomInset, setContentBottomInset] = React.useState(0)
const [isImageViewVisible, setIsImageViewVisible] = React.useState(false)
const [imageViewIndex, setImageViewIndex] = React.useState(0)
const images = messages
.filter((message): message is MessageType.Image => message.type === 'image')
.map((message) => ({ uri: message.imageUrl }))
.reverse()
const list = React.useRef<FlatList<Message>>(null)
const list = React.useRef<FlatList<MessageType.Any>>(null)
const handleSendPress = (message: Message) => {
const handleSendPress = (message: MessageType.Any) => {
onSendPress(message)
list.current?.scrollToOffset({
animated: true,
@@ -34,34 +43,71 @@ export const Chat = ({
})
}
const keyExtractor = (item: Message) => item.id
const keyExtractor = (item: MessageType.Any) => item.id
const renderItem = ({ item }: { item: Message }) => (
<TextMessage message={item} parentComponentSize={size} user={user} />
)
const renderItem = ({
item,
index,
}: {
item: MessageType.Any
index: number
}) => {
const previousMessageSameAuthor =
messages[index - 1]?.authorId === item.authorId
return (
<Message
message={item}
onImagePress={(imageUrl) => {
setImageViewIndex(images.findIndex((image) => image.uri === imageUrl))
setIsImageViewVisible(true)
StatusBar.setHidden(true, 'slide')
}}
parentComponentSize={size}
previousMessageSameAuthor={previousMessageSameAuthor}
/>
)
}
return (
<SafeAreaView style={styles.container} onLayout={onLayout}>
<FlatList
ref={list}
contentContainerStyle={{ paddingTop: contentBottomInset }}
style={styles.list}
data={messages}
renderItem={renderItem}
automaticallyAdjustContentInsets={false}
inverted
keyboardDismissMode='interactive'
keyExtractor={keyExtractor}
scrollIndicatorInsets={{ top: contentBottomInset }}
{...panHandlers}
/>
<Input
onAttachmentPress={onAttachmentPress}
onContentBottomInsetUpdate={setContentBottomInset}
onSendPress={handleSendPress}
panResponderPositionY={positionY}
user={user}
/>
</SafeAreaView>
<UserContext.Provider value={user}>
<SafeAreaView style={styles.container} onLayout={onLayout}>
<FlatList
ref={list}
contentContainerStyle={{ paddingTop: contentBottomInset }}
style={styles.list}
data={messages}
renderItem={renderItem}
automaticallyAdjustContentInsets={false}
inverted
keyboardDismissMode='interactive'
keyExtractor={keyExtractor}
scrollIndicatorInsets={{ top: contentBottomInset }}
ListFooterComponent={<View />}
ListFooterComponentStyle={styles.footer}
{...panHandlers}
/>
<Input
onAttachmentPress={onAttachmentPress}
onContentBottomInsetUpdate={setContentBottomInset}
onSendPress={handleSendPress}
panResponderPositionY={positionY}
textInputProps={textInputProps}
/>
<ImageView
images={images}
imageIndex={imageViewIndex}
// TODO: Tapping on a close button results in the next warning:
// `An update to ImageViewing inside a test was not wrapped in act(...).`
onRequestClose={
/* istanbul ignore next */ () => {
setIsImageViewVisible(false)
StatusBar.setHidden(false, 'slide')
}
}
visible={isImageViewVisible}
/>
</SafeAreaView>
</UserContext.Provider>
)
}

View File

@@ -1,18 +1,37 @@
import { fireEvent, render, waitFor } from '@testing-library/react-native'
import * as React from 'react'
import { fireEvent, render } from 'react-native-testing-library'
import { message, user } from '../../../../jest/fixtures'
import { imageMessage, textMessage, user } from '../../../../jest/fixtures'
import { Chat } from '../Chat'
describe('chat', () => {
it('calls onSendPress', () => {
it('renders image preview', async () => {
expect.assertions(1)
const messages = [message]
const messages = [imageMessage]
const onSendPress = jest.fn()
const { getByA11yLabel } = render(
const { getByRole, getByText } = render(
<Chat messages={messages} onSendPress={onSendPress} user={user} />
)
const button = getByA11yLabel('Send a message')
const button = getByRole('image').parent
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith({ ...message, text: '' })
await waitFor(() => getByText(''))
const closeButton = getByText('✕')
expect(closeButton).toBeDefined()
})
it('sends a text message', () => {
expect.assertions(1)
const messages = [textMessage]
const onSendPress = jest.fn()
const { getByLabelText } = render(
<Chat
messages={messages}
onSendPress={onSendPress}
textInputProps={{ defaultValue: 'text' }}
user={user}
/>
)
const button = getByLabelText('Send a message')
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith(textMessage)
})
})

View File

@@ -4,6 +4,9 @@ export default StyleSheet.create({
container: {
flex: 1,
},
footer: {
height: 24,
},
list: {
backgroundColor: '#fff',
},

View File

@@ -0,0 +1,42 @@
import * as React from 'react'
import { Image, TouchableWithoutFeedback } from 'react-native'
import { MessageType, Size } from '../../types'
import styles from './styles'
export interface ImageMessageProps {
message: MessageType.Image
onPress: (imageUrl: string) => void
}
export const ImageMessage = ({ message, onPress }: ImageMessageProps) => {
const defaultHeight = message.height ?? 0
const defaultWidth = message.width ?? 0
const [size, setSize] = React.useState<Size>({
height: defaultHeight,
width: defaultWidth,
})
const { image } = styles({ size })
React.useEffect(() => {
if (defaultHeight <= 0 || defaultWidth <= 0)
Image.getSize(
message.imageUrl,
(width, height) => setSize({ height, width }),
() => setSize({ height: 0, width: 0 })
)
}, [defaultHeight, defaultWidth, message.imageUrl])
const handlePress = () => {
onPress(message.imageUrl)
}
return (
<TouchableWithoutFeedback onPress={handlePress}>
<Image
accessibilityRole='image'
source={{ uri: message.imageUrl }}
style={image}
/>
</TouchableWithoutFeedback>
)
}

View File

@@ -0,0 +1,49 @@
import { act, fireEvent, render } from '@testing-library/react-native'
import * as React from 'react'
import { Image } from 'react-native'
import { imageMessage, size } from '../../../../jest/fixtures'
import { ImageMessage } from '../ImageMessage'
describe('text message', () => {
it('gets image size and renders', () => {
expect.assertions(4)
const getSizeMock = jest.spyOn(Image, 'getSize')
// eslint-disable-next-line @typescript-eslint/no-empty-function
getSizeMock.mockImplementation(() => {})
const message = { ...imageMessage, height: undefined, width: undefined }
const onPress = jest.fn()
const { getByRole } = render(
<ImageMessage message={message} onPress={onPress} />
)
expect(getSizeMock).toHaveBeenCalledTimes(1)
const getSizeArgs = getSizeMock.mock.calls[0]
expect(getSizeArgs[0]).toBe(imageMessage.imageUrl)
const success = getSizeArgs[1]
const error = getSizeArgs[2]
act(() => {
success(size.width, size.height)
})
const successImageComponent = getByRole('image')
expect(successImageComponent.props).toHaveProperty(
'style.width',
size.width
)
act(() => {
error(new Error())
})
const errorImageComponent = getByRole('image')
expect(errorImageComponent.props).toHaveProperty('style.width', 0)
getSizeMock.mockRestore()
})
it('handles press', () => {
expect.assertions(1)
const onPress = jest.fn()
const { getByRole } = render(
<ImageMessage message={imageMessage} onPress={onPress} />
)
const button = getByRole('image').parent
fireEvent.press(button)
expect(onPress).toHaveBeenCalledWith(imageMessage.imageUrl)
})
})

View File

@@ -0,0 +1 @@
export * from './ImageMessage'

View File

@@ -0,0 +1,12 @@
import { StyleSheet } from 'react-native'
import { Size } from '../../types'
const styles = ({ size }: { size: Size }) =>
StyleSheet.create({
image: {
aspectRatio: size.height > 0 ? size.width / size.height : 1,
width: size.width < 520 ? size.width : '100%',
},
})
export default styles

View File

@@ -1,19 +1,24 @@
import { KeyboardAccessoryView } from '@flyerhq/react-native-keyboard-accessory-view'
import * as React from 'react'
import { Animated, TextInput, TextInputProps, View } from 'react-native'
import { Message, User } from '../../types'
import { uuidv4 } from '../../utils'
import {
Animated,
StyleSheet,
TextInput,
TextInputProps,
View,
} from 'react-native'
import { MessageType, SendImageCallback } from '../../types'
import { UserContext, uuidv4 } from '../../utils'
import { AttachmentButton } from '../AttachmentButton'
import { SendButton } from '../SendButton'
import styles from './styles'
export interface InputProps {
onAttachmentPress?: () => void
onAttachmentPress?: (send: SendImageCallback) => void
onContentBottomInsetUpdate?: (contentBottomInset: number) => void
onSendPress: (message: Message) => void
onSendPress: (message: MessageType.Any) => void
panResponderPositionY?: Animated.Value
textInputProps?: TextInputProps
user: User
}
export const Input = ({
@@ -22,13 +27,21 @@ export const Input = ({
onSendPress,
panResponderPositionY,
textInputProps,
user,
}: InputProps) => {
const user = React.useContext(UserContext)
// Use `defaultValue` if provided
const [text, setText] = React.useState(textInputProps?.defaultValue ?? '')
const value = textInputProps?.value ?? text
const defaultMessageParams = () => ({
// Buttons only rendered when the user exists, so we can safely force unwrap it
/* type-coverage:ignore-next-line */ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
authorId: user!.id,
id: uuidv4(),
timestamp: Math.floor(Date.now() / 1000),
})
const handleChangeText = (newText: string) => {
// Track local state in case `onChangeText` is provided and `value` is not
setText(newText)
@@ -37,14 +50,29 @@ export const Input = ({
const handleSend = () => {
onSendPress({
authorId: user.id,
id: uuidv4(),
text: value,
timestamp: Math.floor(Date.now() / 1000),
...defaultMessageParams(),
text: value.trim(),
type: 'text',
})
setText('')
}
// TODO: This function is binded to the `onAttachmentPress`, how to mock this in tests?
/* istanbul ignore next */
const handleSendImage = ({
height,
imageUrl,
width,
}: Parameters<SendImageCallback>[0]) => {
onSendPress({
...defaultMessageParams(),
height,
imageUrl,
type: 'image',
width,
})
}
return (
<KeyboardAccessoryView
onContentBottomInsetUpdate={onContentBottomInsetUpdate}
@@ -52,7 +80,11 @@ export const Input = ({
style={styles.keyboardAccessoryView}
>
<View style={styles.container}>
<AttachmentButton onPress={onAttachmentPress} />
{user && (
<AttachmentButton
onPress={onAttachmentPress?.bind(null, handleSendImage)}
/>
)}
<TextInput
multiline
placeholder='Your message here'
@@ -60,11 +92,11 @@ export const Input = ({
underlineColorAndroid='transparent'
{...textInputProps}
// Keep our implementation but allow user to use these `TextInputProps`
style={[styles.input, textInputProps?.style]}
style={StyleSheet.flatten([styles.input, textInputProps?.style])}
onChangeText={handleChangeText}
value={value}
/>
<SendButton onPress={handleSend} />
{user && value.trim() ? <SendButton onPress={handleSend} /> : null}
</View>
</KeyboardAccessoryView>
)

View File

@@ -1,100 +1,123 @@
import { fireEvent, render } from '@testing-library/react-native'
import * as React from 'react'
import { fireEvent, render } from 'react-native-testing-library'
import { message, user } from '../../../../jest/fixtures'
import { textMessage, user } from '../../../../jest/fixtures'
import { UserContext } from '../../../utils'
import { Input } from '../Input'
describe('input', () => {
it('sends a correct message', () => {
it('sends a text message', () => {
expect.assertions(2)
const onSendPress = jest.fn()
const { getByPlaceholder, getByA11yLabel } = render(
<Input onSendPress={onSendPress} user={user} />
const { getByPlaceholderText, getByLabelText } = render(
<UserContext.Provider value={user}>
<Input onSendPress={onSendPress} />
</UserContext.Provider>
)
const textInput = getByPlaceholder('Your message here')
const button = getByA11yLabel('Send a message')
const textInput = getByPlaceholderText('Your message here')
fireEvent.changeText(textInput, 'text')
const button = getByLabelText('Send a message')
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith(message)
expect(textInput.props.value).toStrictEqual('')
expect(onSendPress).toHaveBeenCalledWith(textMessage)
expect(textInput.props).toHaveProperty('value', '')
})
it('sends a correct message if onChangeText and value are provided', () => {
it('sends a text message if onChangeText and value are provided', () => {
expect.assertions(2)
const onSendPress = jest.fn()
const value = 'value'
const onChangeText = jest.fn((newValue) => {
rerender(
<Input
onSendPress={onSendPress}
textInputProps={{ onChangeText, value: newValue }}
user={user}
/>
<UserContext.Provider value={user}>
<Input
onSendPress={onSendPress}
textInputProps={{ onChangeText, value: newValue }}
/>
</UserContext.Provider>
)
})
const { getByPlaceholder, getByA11yLabel, rerender } = render(
<Input
onSendPress={onSendPress}
textInputProps={{ onChangeText, value }}
user={user}
/>
const { getByPlaceholderText, getByLabelText, rerender } = render(
<UserContext.Provider value={user}>
<Input
onSendPress={onSendPress}
textInputProps={{ onChangeText, value }}
/>
</UserContext.Provider>
)
const textInput = getByPlaceholder('Your message here')
const button = getByA11yLabel('Send a message')
const textInput = getByPlaceholderText('Your message here')
fireEvent.changeText(textInput, 'text')
const button = getByLabelText('Send a message')
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith(message)
expect(textInput.props.value).toStrictEqual('text')
expect(onSendPress).toHaveBeenCalledWith(textMessage)
expect(textInput.props).toHaveProperty('value', 'text')
})
it('sends a correct message if onChangeText is provided', () => {
it('sends a text message if onChangeText is provided', () => {
expect.assertions(2)
const onSendPress = jest.fn()
const onChangeText = jest.fn()
const { getByPlaceholder, getByA11yLabel } = render(
<Input
onSendPress={onSendPress}
textInputProps={{ onChangeText }}
user={user}
/>
const { getByPlaceholderText, getByLabelText } = render(
<UserContext.Provider value={user}>
<Input onSendPress={onSendPress} textInputProps={{ onChangeText }} />
</UserContext.Provider>
)
const textInput = getByPlaceholder('Your message here')
const button = getByA11yLabel('Send a message')
const textInput = getByPlaceholderText('Your message here')
fireEvent.changeText(textInput, 'text')
const button = getByLabelText('Send a message')
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith(message)
expect(textInput.props.value).toStrictEqual('')
expect(onSendPress).toHaveBeenCalledWith(textMessage)
expect(textInput.props).toHaveProperty('value', '')
})
it('sends a correct message if value is provided', () => {
it('sends a text message if value is provided', () => {
expect.assertions(2)
const onSendPress = jest.fn()
const value = 'value'
const { getByPlaceholder, getByA11yLabel } = render(
<Input onSendPress={onSendPress} textInputProps={{ value }} user={user} />
const { getByPlaceholderText, getByLabelText } = render(
<UserContext.Provider value={user}>
<Input onSendPress={onSendPress} textInputProps={{ value }} />
</UserContext.Provider>
)
const textInput = getByPlaceholder('Your message here')
const button = getByA11yLabel('Send a message')
const textInput = getByPlaceholderText('Your message here')
fireEvent.changeText(textInput, 'text')
const button = getByLabelText('Send a message')
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith({ ...message, text: value })
expect(textInput.props.value).toStrictEqual(value)
expect(onSendPress).toHaveBeenCalledWith({ ...textMessage, text: value })
expect(textInput.props).toHaveProperty('value', value)
})
it('sends a correct message if defaultValue is provided', () => {
it('sends a text message if defaultValue is provided', () => {
expect.assertions(2)
const onSendPress = jest.fn()
const defaultValue = 'defaultValue'
const { getByPlaceholder, getByA11yLabel } = render(
<Input
onSendPress={onSendPress}
textInputProps={{ defaultValue }}
user={user}
/>
const { getByPlaceholderText, getByLabelText } = render(
<UserContext.Provider value={user}>
<Input onSendPress={onSendPress} textInputProps={{ defaultValue }} />
</UserContext.Provider>
)
const textInput = getByPlaceholder('Your message here')
const button = getByA11yLabel('Send a message')
const textInput = getByPlaceholderText('Your message here')
const button = getByLabelText('Send a message')
fireEvent.press(button)
expect(onSendPress).toHaveBeenCalledWith({ ...message, text: defaultValue })
expect(textInput.props.value).toStrictEqual('')
expect(onSendPress).toHaveBeenCalledWith({
...textMessage,
text: defaultValue,
})
expect(textInput.props).toHaveProperty('value', '')
})
it('sends an image message', () => {
expect.assertions(1)
const onAttachmentPress = jest.fn()
const onSendPress = jest.fn()
const { getByLabelText } = render(
<UserContext.Provider value={user}>
<Input
onAttachmentPress={onAttachmentPress}
onSendPress={onSendPress}
/>
</UserContext.Provider>
)
const button = getByLabelText('Add an attachment')
fireEvent.press(button)
expect(onAttachmentPress).toHaveBeenCalledTimes(1)
})
})

View File

@@ -2,27 +2,26 @@ import { StyleSheet } from 'react-native'
export default StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
padding: 24,
flexDirection: 'row',
paddingHorizontal: 24,
paddingVertical: 20,
},
input: {
color: '#fff',
flex: 1,
fontSize: 16,
fontWeight: '500',
lineHeight: 20,
maxHeight: 200,
// Fixes default Android paddings
margin: 0,
padding: 0,
// Fixes default paddings
paddingBottom: 0,
paddingHorizontal: 16,
paddingBottom: 8,
// Fixes iOS top padding for multiline
paddingTop: 8,
flex: 1,
paddingTop: 0,
},
keyboardAccessoryView: {
backgroundColor: '#000',
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
},
})

View File

@@ -0,0 +1,44 @@
import * as React from 'react'
import { View } from 'react-native'
import { MessageType, Size } from '../../types'
import { UserContext } from '../../utils'
import { ImageMessage } from '../ImageMessage'
import { TextMessage } from '../TextMessage'
import styles from './styles'
export interface MessageProps {
message: MessageType.Any
onImagePress: (imageUrl: string) => void
parentComponentSize: Size
previousMessageSameAuthor: boolean
}
export const Message = ({
message,
onImagePress,
parentComponentSize,
previousMessageSameAuthor,
}: MessageProps) => {
const user = React.useContext(UserContext)
const { container, contentContainer } = styles({
message,
parentComponentSize,
previousMessageSameAuthor,
user,
})
const renderMessage = () => {
switch (message.type) {
case 'image':
return <ImageMessage message={message} onPress={onImagePress} />
case 'text':
return <TextMessage message={message} />
}
}
return (
<View style={container}>
<View style={contentContainer}>{renderMessage()}</View>
</View>
)
}

View File

@@ -0,0 +1 @@
export * from './Message'

View File

@@ -0,0 +1,39 @@
import { StyleSheet } from 'react-native'
import { MessageType, Size, User } from '../../types'
const styles = ({
message,
parentComponentSize,
previousMessageSameAuthor,
user,
}: {
message: MessageType.Any
parentComponentSize: Size
previousMessageSameAuthor: boolean
user?: User
}) =>
StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: user?.id === message.authorId ? 'flex-end' : 'flex-start',
marginBottom: previousMessageSameAuthor ? 8 : 24,
},
contentContainer: {
backgroundColor:
user?.id !== message.authorId || message.type === 'image'
? '#f7f7f8'
: '#6054c9',
borderBottomLeftRadius: user?.id === message.authorId ? 20 : 0,
borderBottomRightRadius: user?.id === message.authorId ? 0 : 20,
borderRadius: 20,
marginHorizontal: 24,
maxWidth:
parentComponentSize.width * 0.8 < 520
? parentComponentSize.width * 0.8
: 520,
overflow: 'hidden',
},
})
export default styles

View File

@@ -7,13 +7,11 @@ import {
} from 'react-native'
export interface SendButtonProps {
disabled?: boolean
onPress: () => void
touchableOpacityProps?: TouchableOpacityProps
}
export const SendButton = ({
disabled,
onPress,
touchableOpacityProps,
}: SendButtonProps) => {
@@ -26,8 +24,6 @@ export const SendButton = ({
<TouchableOpacity
accessibilityRole='button'
accessibilityLabel='Send a message'
accessibilityState={{ disabled }}
disabled={disabled}
{...touchableOpacityProps}
onPress={handlePress}
>

View File

@@ -1,14 +0,0 @@
import * as React from 'react'
import { fireEvent, render } from 'react-native-testing-library'
import { SendButton } from '../SendButton'
describe('send button', () => {
it('sends an event', () => {
expect.assertions(1)
const onPress = jest.fn()
const { getByA11yLabel } = render(<SendButton onPress={onPress} />)
const button = getByA11yLabel('Send a message')
fireEvent.press(button)
expect(onPress).toHaveBeenCalledWith()
})
})

View File

@@ -1,32 +1,23 @@
import * as React from 'react'
import { Text, View } from 'react-native'
import { Message, Size, User } from '../../types'
import { Text } from 'react-native'
import { MessageType } from '../../types'
import { UserContext } from '../../utils'
import styles from './styles'
export interface TextMessageProps {
message: Message
parentComponentSize: Size
user: User
message: MessageType.Text
}
export const TextMessage = ({
message,
parentComponentSize,
user,
}: TextMessageProps) => {
const { container, message: messageStyle, messageContainer } = styles({
export const TextMessage = ({ message }: TextMessageProps) => {
const user = React.useContext(UserContext)
const { text } = styles({
message,
parentComponentSize,
user,
})
return (
<View style={container}>
<View style={messageContainer}>
<Text accessibilityRole='text' style={messageStyle}>
{message.text}
</Text>
</View>
</View>
<Text accessibilityRole='text' style={text}>
{message.text}
</Text>
)
}

View File

@@ -1,16 +0,0 @@
import * as React from 'react'
import { render } from 'react-native-testing-library'
import { message, size, user } from '../../../../jest/fixtures'
import { TextMessage } from '../TextMessage'
describe('text message', () => {
it('renders text', () => {
expect.assertions(1)
const text = 'text'
const { getByText } = render(
<TextMessage message={message} parentComponentSize={size} user={user} />
)
const textComponent = getByText(text)
expect(textComponent).toBeDefined()
})
})

View File

@@ -1,42 +1,21 @@
import { StyleSheet } from 'react-native'
import { Message, Size, User } from '../../types'
import { MessageType, User } from '../../types'
const styles = ({
message,
parentComponentSize,
user,
}: {
message: Message
parentComponentSize: Size
user: User
message: MessageType.Text
user?: User
}) =>
StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
marginVertical: 8,
justifyContent: user.id === message.authorId ? 'flex-end' : 'flex-start',
},
messageContainer: {
paddingHorizontal: 24,
marginHorizontal: 24,
paddingVertical: 20,
borderRadius: 16,
overflow: 'hidden',
borderWidth: 1,
borderBottomLeftRadius: user.id === message.authorId ? 16 : 0,
borderBottomRightRadius: user.id === message.authorId ? 0 : 16,
borderColor: user.id === message.authorId ? '#00cdbd' : '#72738e1f',
backgroundColor: user.id === message.authorId ? '#00cdbd' : '#fff',
maxWidth:
parentComponentSize.width * 0.9 < 520
? parentComponentSize.width * 0.9
: 520,
},
message: {
text: {
color: user?.id === message.authorId ? '#fff' : '#2e2c2c',
fontSize: 16,
fontWeight: '500',
color: user.id === message.authorId ? '#fff' : '#2e2c2c',
lineHeight: 20,
marginHorizontal: 24,
marginVertical: 16,
},
})

View File

@@ -1,5 +1,7 @@
export * from './AttachmentButton'
export * from './Chat'
export * from './ImageMessage'
export * from './Input'
export * from './Message'
export * from './SendButton'
export * from './TextMessage'

View File

@@ -1,10 +1,32 @@
export interface Message {
authorId: string
id: string
text: string
timestamp: number
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace MessageType {
export type Any = Image | Text
interface Base {
authorId: string
id: string
timestamp: number
}
export interface Image extends Base {
height?: number
imageUrl: string
type: 'image'
width?: number
}
export interface Text extends Base {
text: string
type: 'text'
}
}
export type SendImageCallback = (payload: {
height?: number
imageUrl: string
width?: number
}) => void
export interface Size {
height: number
width: number

View File

@@ -1,4 +1,8 @@
import * as React from 'react'
import Blob from 'react-native/Libraries/Blob/Blob'
import { User } from '../types'
export const UserContext = React.createContext<User | undefined>(undefined)
export const getTextSizeInBytes = (text: string) => {
return new Blob([text]).size

1636
yarn.lock

File diff suppressed because it is too large Load Diff