diff --git a/examples/react-native-chat-app/.buckconfig b/examples/react-native-chat-app/.buckconfig
new file mode 100644
index 000000000..934256cb2
--- /dev/null
+++ b/examples/react-native-chat-app/.buckconfig
@@ -0,0 +1,6 @@
+
+[android]
+ target = Google Inc.:Google APIs:23
+
+[maven_repositories]
+ central = https://repo1.maven.org/maven2
diff --git a/examples/react-native-chat-app/.flowconfig b/examples/react-native-chat-app/.flowconfig
new file mode 100644
index 000000000..ee340094c
--- /dev/null
+++ b/examples/react-native-chat-app/.flowconfig
@@ -0,0 +1,96 @@
+[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/.*
+
+# Ignore generators
+.*/local-cli/generator.*
+
+# Ignore BUCK generated folders
+.*\.buckd/
+
+.*/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/examples/react-native-chat-app/.gitignore b/examples/react-native-chat-app/.gitignore
new file mode 100644
index 000000000..42c9490e5
--- /dev/null
+++ b/examples/react-native-chat-app/.gitignore
@@ -0,0 +1,40 @@
+# 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
+
+# BUCK
+buck-out/
+\.buckd/
+android/app/libs
+android/keystores/debug.keystore
diff --git a/examples/react-native-chat-app/.watchmanconfig b/examples/react-native-chat-app/.watchmanconfig
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/examples/react-native-chat-app/.watchmanconfig
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/examples/react-native-chat-app/README.md b/examples/react-native-chat-app/README.md
new file mode 100644
index 000000000..903b59332
--- /dev/null
+++ b/examples/react-native-chat-app/README.md
@@ -0,0 +1,41 @@
+# Horizon Chat example using React
+
+
+
+React Chat Example in React Native.
+
+## Todo
+- [ ] Auth in horizon needs to be fixed rethinkdb/horizon#255. Works with a disabled auth (see "How to start")
+- [ ] Add Android
+- [ ] Better error handling for more stability
+- [ ] Fix visual gitches
+
+## How to start
+
+Install React Native if not already installed.
+```bash
+* npm install -g react-native-cli
+```
+
+Install local dependencies.
+```bash
+npm install
+```
+
+Until Issue rethinkdb/horizon#255 is resolved. Disable auth by patch auth.js
+```bash
+vi +97 ./node_modules/@horizon/client/lib/auth.js
+In line 97 add a return false to setAuthFromQueryParams to exit without doing anything
+add a `return false` to disable it
+```
+
+Start your Database
+```bash
+$ hz serve --dev .
+```
+
+Start React Native & iOS Simulator
+```bash
+$ npm start
+```
+
diff --git a/examples/react-native-chat-app/android/app/BUCK b/examples/react-native-chat-app/android/app/BUCK
new file mode 100644
index 000000000..bc1f108fb
--- /dev/null
+++ b/examples/react-native-chat-app/android/app/BUCK
@@ -0,0 +1,66 @@
+import re
+
+# To learn about Buck see [Docs](https://buckbuild.com/).
+# To run your application with Buck:
+# - install Buck
+# - `npm start` - to start the packager
+# - `cd android`
+# - `cp ~/.android/debug.keystore keystores/debug.keystore`
+# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
+# - `buck install -r android/app` - compile, install and run application
+#
+
+lib_deps = []
+for jarfile in glob(['libs/*.jar']):
+ name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
+ lib_deps.append(':' + name)
+ prebuilt_jar(
+ name = name,
+ binary_jar = jarfile,
+ )
+
+for aarfile in glob(['libs/*.aar']):
+ name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
+ lib_deps.append(':' + name)
+ android_prebuilt_aar(
+ name = name,
+ aar = aarfile,
+ )
+
+android_library(
+ name = 'all-libs',
+ exported_deps = lib_deps
+)
+
+android_library(
+ name = 'app-code',
+ srcs = glob([
+ 'src/main/java/**/*.java',
+ ]),
+ deps = [
+ ':all-libs',
+ ':build_config',
+ ':res',
+ ],
+)
+
+android_build_config(
+ name = 'build_config',
+ package = 'com.reactnativechatapp',
+)
+
+android_resource(
+ name = 'res',
+ res = 'src/main/res',
+ package = 'com.reactnativechatapp',
+)
+
+android_binary(
+ name = 'app',
+ package_type = 'debug',
+ manifest = 'src/main/AndroidManifest.xml',
+ keystore = '//android/keystores:debug',
+ deps = [
+ ':app-code',
+ ],
+)
diff --git a/examples/react-native-chat-app/android/app/build.gradle b/examples/react-native-chat-app/android/app/build.gradle
new file mode 100644
index 000000000..73023079f
--- /dev/null
+++ b/examples/react-native-chat-app/android/app/build.gradle
@@ -0,0 +1,133 @@
+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: "../../node_modules/react-native/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: "../../node_modules/react-native/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.reactnativechatapp"
+ 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
+}
+
+// Run this once to be able to run the application with BUCK
+// puts all compile dependencies into folder libs for BUCK to use
+task copyDownloadableDepsToLibs(type: Copy) {
+ from configurations.compile
+ into 'libs'
+}
diff --git a/examples/react-native-chat-app/android/app/proguard-rules.pro b/examples/react-native-chat-app/android/app/proguard-rules.pro
new file mode 100644
index 000000000..7d72e4692
--- /dev/null
+++ b/examples/react-native-chat-app/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/examples/react-native-chat-app/android/app/src/main/AndroidManifest.xml b/examples/react-native-chat-app/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..9a99ab4d2
--- /dev/null
+++ b/examples/react-native-chat-app/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/react-native-chat-app/android/app/src/main/java/com/reactnativechatapp/MainActivity.java b/examples/react-native-chat-app/android/app/src/main/java/com/reactnativechatapp/MainActivity.java
new file mode 100644
index 000000000..853f60d9a
--- /dev/null
+++ b/examples/react-native-chat-app/android/app/src/main/java/com/reactnativechatapp/MainActivity.java
@@ -0,0 +1,40 @@
+package com.reactnativechatapp;
+
+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 "ReactNativeChatApp";
+ }
+
+ /**
+ * 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/examples/react-native-chat-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/react-native-chat-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..cde69bccc
Binary files /dev/null and b/examples/react-native-chat-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/examples/react-native-chat-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/react-native-chat-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..c133a0cbd
Binary files /dev/null and b/examples/react-native-chat-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/examples/react-native-chat-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/react-native-chat-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..bfa42f0e7
Binary files /dev/null and b/examples/react-native-chat-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/examples/react-native-chat-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/react-native-chat-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..324e72cdd
Binary files /dev/null and b/examples/react-native-chat-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/examples/react-native-chat-app/android/app/src/main/res/values/strings.xml b/examples/react-native-chat-app/android/app/src/main/res/values/strings.xml
new file mode 100644
index 000000000..34e5ee439
--- /dev/null
+++ b/examples/react-native-chat-app/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ ReactNativeChatApp
+
diff --git a/examples/react-native-chat-app/android/app/src/main/res/values/styles.xml b/examples/react-native-chat-app/android/app/src/main/res/values/styles.xml
new file mode 100644
index 000000000..319eb0ca1
--- /dev/null
+++ b/examples/react-native-chat-app/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/examples/react-native-chat-app/android/build.gradle b/examples/react-native-chat-app/android/build.gradle
new file mode 100644
index 000000000..403a00756
--- /dev/null
+++ b/examples/react-native-chat-app/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/examples/react-native-chat-app/android/gradle.properties b/examples/react-native-chat-app/android/gradle.properties
new file mode 100644
index 000000000..1fd964e90
--- /dev/null
+++ b/examples/react-native-chat-app/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/examples/react-native-chat-app/android/gradle/wrapper/gradle-wrapper.jar b/examples/react-native-chat-app/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..b5166dad4
Binary files /dev/null and b/examples/react-native-chat-app/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/examples/react-native-chat-app/android/gradle/wrapper/gradle-wrapper.properties b/examples/react-native-chat-app/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..b9fbfaba0
--- /dev/null
+++ b/examples/react-native-chat-app/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/examples/react-native-chat-app/android/gradlew b/examples/react-native-chat-app/android/gradlew
new file mode 100755
index 000000000..91a7e269e
--- /dev/null
+++ b/examples/react-native-chat-app/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/examples/react-native-chat-app/android/gradlew.bat b/examples/react-native-chat-app/android/gradlew.bat
new file mode 100644
index 000000000..aec99730b
--- /dev/null
+++ b/examples/react-native-chat-app/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/examples/react-native-chat-app/android/keystores/BUCK b/examples/react-native-chat-app/android/keystores/BUCK
new file mode 100644
index 000000000..15da20e6b
--- /dev/null
+++ b/examples/react-native-chat-app/android/keystores/BUCK
@@ -0,0 +1,8 @@
+keystore(
+ name = 'debug',
+ store = 'debug.keystore',
+ properties = 'debug.keystore.properties',
+ visibility = [
+ 'PUBLIC',
+ ],
+)
diff --git a/examples/react-native-chat-app/android/keystores/debug.keystore.properties b/examples/react-native-chat-app/android/keystores/debug.keystore.properties
new file mode 100644
index 000000000..121bfb49f
--- /dev/null
+++ b/examples/react-native-chat-app/android/keystores/debug.keystore.properties
@@ -0,0 +1,4 @@
+key.store=debug.keystore
+key.alias=androiddebugkey
+key.store.password=android
+key.alias.password=android
diff --git a/examples/react-native-chat-app/android/settings.gradle b/examples/react-native-chat-app/android/settings.gradle
new file mode 100644
index 000000000..29cb5b12c
--- /dev/null
+++ b/examples/react-native-chat-app/android/settings.gradle
@@ -0,0 +1,3 @@
+rootProject.name = 'ReactNativeChatApp'
+
+include ':app'
diff --git a/examples/react-native-chat-app/app.css b/examples/react-native-chat-app/app.css
new file mode 100644
index 000000000..c816fa205
--- /dev/null
+++ b/examples/react-native-chat-app/app.css
@@ -0,0 +1,50 @@
+/* always present */
+.expand-transition {
+ transition: all .4s ease;
+ height: 30px;
+ padding: 10px;
+ background-color: #eee;
+ overflow: hidden;
+}
+
+/* .expand-enter defines the starting state for entering */
+/* .expand-leave defines the ending state for leaving */
+.expand-enter, .expand-leave {
+ height: 0;
+ padding: 0 10px;
+ opacity: 0;
+}
+
+#app ul {
+ list-style-type: none;
+}
+
+.message {
+ height: 50px;
+}
+
+.message img {
+ vertical-align:middle;
+}
+
+.message .text {
+ vertical-align:middle;
+ margin-left:5px;
+ font-family: 'Source Code Pro', "Raleway", "Helvetica Neue";
+ font-size:20px;
+}
+
+.message .datetime {
+ color:darkgrey;
+}
+
+#input {
+ margin-bottom:10%;
+}
+
+#input input {
+ height:100px;
+ font-size:5rem;
+ padding:10px;
+ font-family: 'Source Code Pro', "Raleway", "Helvetica Neue";
+}
diff --git a/examples/react-native-chat-app/app.jsx b/examples/react-native-chat-app/app.jsx
new file mode 100644
index 000000000..b93a968e4
--- /dev/null
+++ b/examples/react-native-chat-app/app.jsx
@@ -0,0 +1,187 @@
+/*jshint quotmark:false */
+/*jshint white:false */
+/*jshint trailing:false */
+/*jshint newcap:false */
+
+var app = app || {};
+
+(function(){
+ 'use strict';
+
+ //Setup Horizon connection
+ const horizon = Horizon();
+
+ app.ChatApp = React.createClass({
+
+ uuid: function () {
+ /*jshint bitwise:false */
+ var i, random;
+ var uuid = '';
+
+ for (i = 0; i < 32; i++) {
+ random = Math.random() * 16 | 0;
+ if (i === 8 || i === 12 || i === 16 || i === 20) {
+ uuid += '-';
+ }
+ uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
+ .toString(16);
+ }
+ return uuid;
+ },
+
+ getDefaultProps: function(){
+
+ const time = new Date().getMilliseconds();
+
+ // Precache the avatar image so it immediately shows on input enter.
+ const image = new Image();
+ image.src = `http://api.adorable.io/avatars/50/${time}.png`;
+
+ return {
+ horizon: horizon("react_messages"),
+ avatarUrl: image.src,
+ authorId: time
+ };
+ },
+
+ getInitialState: function(){
+ return {
+ disabled: true,
+ messages: []
+ };
+ },
+
+ componentDidMount: function(){
+ // As soon as this component is mounted, enable the input
+ this.setState({
+ disabled: false,
+ });
+
+ // Initiate the changefeeds
+ this.subscribe();
+ },
+
+ save: function(message){
+ //Save method for handling messages
+ this.props.horizon.store({
+ id: this.uuid(),
+ text: message,
+ authorId: this.props.authorId,
+ datetime: new Date()
+ }).subscribe();
+ },
+
+ subscribe: function(){
+ this.props.horizon
+ .order("datetime", "descending")
+ .limit(8)
+ .watch()
+ .subscribe(messages => {
+ this.setState({ messages: messages })
+ })
+ },
+
+ render: function(){
+ return (
+
+ );
+ }
+ });
+
+ app.ChatInput = React.createClass({
+ getDefaultProps: function(){
+ // Set default props for enter key
+ return {
+ ENTER_KEY: 13
+ };
+ },
+
+ getInitialState: function(){
+ // Initial state of the inputText is blank ""
+ return {
+ inputText: ""
+ }
+ },
+
+ handleKeyDown: function(event){
+ // Checking if enter key has been pressed to handle contents of
+ // input field value.
+ if(event.keyCode === this.props.ENTER_KEY){
+ const val = this.state.inputText.trim();
+ if (val){
+ // Save the value
+ this.props.onSave(val);
+ // Empty the input value
+ this.setState({inputText: ""});
+ }
+ }
+ },
+
+ handleChange: function(event){
+ // Every time the value of the input field changes we update the state
+ // object to have the value of the input field.
+ this.setState({
+ inputText: event.target.value
+ });
+ },
+
+ render: function(){
+ return (
+