diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj index 2f62d3066d6..6396f984627 100644 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj +++ b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj @@ -1028,7 +1028,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.facebook.internal.uiexplorer.local; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = UIExplorer; TARGETED_DEVICE_FAMILY = "1,2"; WARNING_CFLAGS = ( @@ -1054,7 +1054,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.facebook.internal.uiexplorer.local; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = UIExplorer; TARGETED_DEVICE_FAMILY = "1,2"; WARNING_CFLAGS = ( diff --git a/Examples/UIExplorer/UIExplorer/AppDelegate.m b/Examples/UIExplorer/UIExplorer/AppDelegate.m index b0d19a59c17..39bb963e2c0 100644 --- a/Examples/UIExplorer/UIExplorer/AppDelegate.m +++ b/Examples/UIExplorer/UIExplorer/AppDelegate.m @@ -24,15 +24,22 @@ @end @implementation AppDelegate - - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; - + + // Appetizer.io params check + NSDictionary *initProps = nil; + NSString *_routeUri = [[NSUserDefaults standardUserDefaults] stringForKey:@"route"]; + if (_routeUri) { + initProps = @{@"exampleFromAppetizeParams": + [NSString stringWithFormat:@"rnuiexplorer://example/%@Example", _routeUri]}; + } + RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:_bridge moduleName:@"UIExplorerApp" - initialProperties:nil]; + initialProperties:initProps]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; diff --git a/Examples/UIExplorer/UIExplorerApp.android.js b/Examples/UIExplorer/UIExplorerApp.android.js index 2488def4364..c8e451e9cc5 100644 --- a/Examples/UIExplorer/UIExplorerApp.android.js +++ b/Examples/UIExplorer/UIExplorerApp.android.js @@ -31,19 +31,46 @@ const { const { RootContainer: NavigationRootContainer, } = NavigationExperimental; -const UIExplorerActions = require('./UIExplorerActions'); const UIExplorerExampleList = require('./UIExplorerExampleList'); const UIExplorerList = require('./UIExplorerList'); const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer'); const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap'); +const URIActionMap = require('./URIActionMap'); var DRAWER_WIDTH_LEFT = 56; +type Props = { + exampleFromAppetizeParams: string, +}; + +type State = { + initialExampleUri: ?string, +}; + class UIExplorerApp extends React.Component { + _handleOpenInitialExample: Function; + state: State; + constructor(props: Props) { + super(props); + this._handleOpenInitialExample = this._handleOpenInitialExample.bind(this); + this.state = { + initialExampleUri: props.exampleFromAppetizeParams, + }; + } + componentWillMount() { BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress.bind(this)); } + componentDidMount() { + // There's a race condition if we try to navigate to the specified example + // from the initial props at the same time the navigation logic is setting + // up the initial navigation state. This hack adds a delay to avoid this + // scenario. So after the initial example list is shown, we then transition + // to the initial example. + setTimeout(this._handleOpenInitialExample, 500); + } + render() { return ( { this._navigationRootRef = navRootRef; }} reducer={UIExplorerNavigationReducer} renderNavigation={this._renderApp.bind(this)} + linkingActionMap={URIActionMap} /> ); } + _handleOpenInitialExample() { + if (this.state.initialExampleUri) { + const exampleAction = URIActionMap(this.state.initialExampleUri); + if (exampleAction && this._navigationRootRef) { + this._navigationRootRef.handleNavigation(exampleAction); + } + } + this.setState({initialExampleUri: null}); + } + _renderApp(navigationState, onNavigate) { if (!navigationState) { return null; diff --git a/Examples/UIExplorer/UIExplorerApp.ios.js b/Examples/UIExplorer/UIExplorerApp.ios.js index caccd255ebc..92c6a1ccf0c 100644 --- a/Examples/UIExplorer/UIExplorerApp.ios.js +++ b/Examples/UIExplorer/UIExplorerApp.ios.js @@ -24,14 +24,13 @@ 'use strict'; const React = require('react-native'); -const UIExplorerActions = require('./UIExplorerActions'); const UIExplorerList = require('./UIExplorerList.ios'); const UIExplorerExampleList = require('./UIExplorerExampleList'); const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer'); const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap'); +const URIActionMap = require('./URIActionMap'); const { - Alert, AppRegistry, NavigationExperimental, SnapshotViewIOS, @@ -51,32 +50,13 @@ import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer'; import type { UIExplorerExample } from './UIExplorerList.ios'; -function PathActionMap(path: string): ?Object { - // Warning! Hacky parsing for example code. Use a library for this! - const exampleParts = path.split('/example/'); - const exampleKey = exampleParts[1]; - if (exampleKey) { - if (!UIExplorerList.Modules[exampleKey]) { - Alert.alert(`${exampleKey} example could not be found!`); - return null; - } - return UIExplorerActions.ExampleAction(exampleKey); - } - return null; -} +type Props = { + exampleFromAppetizeParams: string, +}; -function URIActionMap(uri: ?string): ?Object { - // Warning! Hacky parsing for example code. Use a library for this! - if (!uri) { - return null; - } - const parts = uri.split('rnuiexplorer:/'); - if (!parts[1]) { - return null; - } - const path = parts[1]; - return PathActionMap(path); -} +type State = { + initialExampleUri: ?string, +}; class UIExplorerApp extends React.Component { _navigationRootRef: ?NavigationRootContainer; @@ -85,12 +65,29 @@ class UIExplorerApp extends React.Component { _renderScene: Function; _renderCard: Function; _renderTitleComponent: Function; + _handleOpenInitialExample: Function; + state: State; + constructor(props: Props) { + super(props); + this._handleOpenInitialExample = this._handleOpenInitialExample.bind(this); + this.state = { + initialExampleUri: props.exampleFromAppetizeParams, + }; + } componentWillMount() { this._renderNavigation = this._renderNavigation.bind(this); this._renderOverlay = this._renderOverlay.bind(this); this._renderScene = this._renderScene.bind(this); this._renderTitleComponent = this._renderTitleComponent.bind(this); } + componentDidMount() { + // There's a race condition if we try to navigate to the specified example + // from the initial props at the same time the navigation logic is setting + // up the initial navigation state. This hack adds a delay to avoid this + // scenario. So after the initial example list is shown, we then transition + // to the initial example. + setTimeout(this._handleOpenInitialExample, 500); + } render() { return ( ); } + _handleOpenInitialExample() { + if (this.state.initialExampleUri) { + const exampleAction = URIActionMap(this.state.initialExampleUri); + if (exampleAction && this._navigationRootRef) { + this._navigationRootRef.handleNavigation(exampleAction); + } + } + this.setState({initialExampleUri: null}); + } _renderNavigation(navigationState: UIExplorerNavigationState, onNavigate: Function) { if (!navigationState) { return null; diff --git a/Examples/UIExplorer/URIActionMap.js b/Examples/UIExplorer/URIActionMap.js new file mode 100644 index 00000000000..fa2d026ca54 --- /dev/null +++ b/Examples/UIExplorer/URIActionMap.js @@ -0,0 +1,54 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @flow + */ +'use strict'; + +const React = require('react-native'); +const UIExplorerActions = require('./UIExplorerActions'); +// $FlowFixMe : This is a platform-forked component, and flow seems to only run on iOS? +const UIExplorerList = require('./UIExplorerList'); + +const { + Alert, +} = React; + +function PathActionMap(path: string): ?Object { + // Warning! Hacky parsing for example code. Use a library for this! + const exampleParts = path.split('/example/'); + const exampleKey = exampleParts[1]; + if (exampleKey) { + if (!UIExplorerList.Modules[exampleKey]) { + Alert.alert(`${exampleKey} example could not be found!`); + return null; + } + return UIExplorerActions.ExampleAction(exampleKey); + } + return null; +} + +function URIActionMap(uri: ?string): ?Object { + // Warning! Hacky parsing for example code. Use a library for this! + if (!uri) { + return null; + } + const parts = uri.split('rnuiexplorer:/'); + if (!parts[1]) { + return null; + } + const path = parts[1]; + return PathActionMap(path); +} + +module.exports = URIActionMap; diff --git a/Examples/UIExplorer/android/app/build.gradle b/Examples/UIExplorer/android/app/build.gradle index fae695a347e..ea65dc6a8cc 100644 --- a/Examples/UIExplorer/android/app/build.gradle +++ b/Examples/UIExplorer/android/app/build.gradle @@ -1,5 +1,87 @@ apply plugin: 'com.android.application' +import com.android.build.OutputFile + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation + * entryFile: "index.android.js", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property is in the format 'bundleIn${productFlavor}${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/**"] + * ] + */ + +project.ext.react = [ + bundleAssetName: "UIExplorerApp.android.bundle", + entryFile: file("../../UIExplorerApp.android.js"), + root: "../../../../", + inputExcludes: ["android/**", "./**"] +] + +apply from: "react.gradle" + +/** + * Set this to true to create three separate APKs instead of one: + * - A universal APK that works on all devices + * - 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" @@ -14,10 +96,40 @@ android { abiFilters "armeabi-v7a", "x86" } } + signingConfigs { + release { + storeFile file(MYAPP_RELEASE_STORE_FILE) + storePassword MYAPP_RELEASE_STORE_PASSWORD + keyAlias MYAPP_RELEASE_KEY_ALIAS + keyPassword MYAPP_RELEASE_KEY_PASSWORD + } + } + splits { + abi { + enable enableSeparateBuildPerCPUArchitecture + universalApk false + reset() + include "armeabi-v7a", "x86" + } + } buildTypes { release { - minifyEnabled false + minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + } + // 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 + } } } } diff --git a/Examples/UIExplorer/android/app/gradle.properties b/Examples/UIExplorer/android/app/gradle.properties index dfbe478748b..74027349d96 100644 --- a/Examples/UIExplorer/android/app/gradle.properties +++ b/Examples/UIExplorer/android/app/gradle.properties @@ -1 +1,5 @@ android.useDeprecatedNdk=true +MYAPP_RELEASE_STORE_FILE=my-release-key.keystore +MYAPP_RELEASE_KEY_ALIAS=my-key-alias +MYAPP_RELEASE_STORE_PASSWORD=***** +MYAPP_RELEASE_KEY_PASSWORD=***** diff --git a/Examples/UIExplorer/android/app/react.gradle b/Examples/UIExplorer/android/app/react.gradle new file mode 100644 index 00000000000..c0dca024c8d --- /dev/null +++ b/Examples/UIExplorer/android/app/react.gradle @@ -0,0 +1,96 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +def config = project.hasProperty("react") ? project.react : []; + +def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" +def entryFile = config.entryFile ?: "index.android.js" + +// because elvis operator +def elvisFile(thing) { + return thing ? file(thing) : null; +} + +def reactRoot = elvisFile(config.root) ?: file("../../") +def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] + +void runBefore(String dependentTaskName, Task task) { + Task dependentTask = tasks.findByPath(dependentTaskName); + if (dependentTask != null) { + dependentTask.dependsOn task + } +} + +gradle.projectsEvaluated { + // Grab all build types and product flavors + def buildTypes = android.buildTypes.collect { type -> type.name } + def productFlavors = android.productFlavors.collect { flavor -> flavor.name } + + // When no product flavors defined, use empty + if (!productFlavors) productFlavors.add('') + + productFlavors.each { productFlavorName -> + buildTypes.each { buildTypeName -> + // Create variant and source names + def sourceName = "${buildTypeName}" + def targetName = "${sourceName.capitalize()}" + if (productFlavorName) { + sourceName = "${productFlavorName}${targetName}" + } + + // React js bundle directories + def jsBundleDirConfigName = "jsBundleDir${targetName}" + def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: + file("$buildDir/intermediates/assets/${sourceName}") + + def resourcesDirConfigName = "jsBundleDir${targetName}" + def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?: + file("$buildDir/intermediates/res/merged/${sourceName}") + def jsBundleFile = file("$jsBundleDir/$bundleAssetName") + + // Bundle task name for variant + def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets" + + def currentBundleTask = tasks.create( + name: bundleJsAndAssetsTaskName, + type: Exec) { + group = "react" + description = "bundle JS and assets for ${targetName}." + + // Create dirs if they are not there (e.g. the "clean" task just ran) + doFirst { + jsBundleDir.mkdirs() + resourcesDir.mkdirs() + } + + // Set up inputs and outputs so gradle can cache the result + inputs.files fileTree(dir: reactRoot, excludes: inputExcludes) + outputs.dir jsBundleDir + outputs.dir resourcesDir + + // Set up the call to the react-native cli + workingDir reactRoot + + // Set up dev mode + def devEnabled = !targetName.toLowerCase().contains("release") + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine "cmd", "/c", "node", "./local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}", + "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir + } else { + commandLine "node", "./local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}", + "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir + } + + enabled config."bundleIn${targetName}" ?: targetName.toLowerCase().contains("release") + } + + // Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process + currentBundleTask.dependsOn("merge${targetName}Resources") + currentBundleTask.dependsOn("merge${targetName}Assets") + + runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask) + runBefore("processX86${targetName}Resources", currentBundleTask) + runBefore("processUniversal${targetName}Resources", currentBundleTask) + runBefore("process${targetName}Resources", currentBundleTask) + } + } +} diff --git a/Examples/UIExplorer/android/app/src/main/AndroidManifest.xml b/Examples/UIExplorer/android/app/src/main/AndroidManifest.xml index c1e8475153e..5a9d5962a86 100644 --- a/Examples/UIExplorer/android/app/src/main/AndroidManifest.xml +++ b/Examples/UIExplorer/android/app/src/main/AndroidManifest.xml @@ -20,6 +20,13 @@ + + + + + + + diff --git a/Examples/UIExplorer/android/app/src/main/java/UIExplorerActivity.java b/Examples/UIExplorer/android/app/src/main/java/UIExplorerActivity.java index f9a50e93f44..e18e4f25c50 100644 --- a/Examples/UIExplorer/android/app/src/main/java/UIExplorerActivity.java +++ b/Examples/UIExplorer/android/app/src/main/java/UIExplorerActivity.java @@ -23,7 +23,32 @@ import java.util.Arrays; import java.util.List; import javax.annotation.Nullable; +import android.os.Bundle; + public class UIExplorerActivity extends ReactActivity { + private final String PARAM_ROUTE = "route"; + private Bundle mInitialProps = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + // Get remote param before calling super which uses it + Bundle bundle = getIntent().getExtras(); + if (bundle != null && bundle.containsKey(PARAM_ROUTE)) { + String routeUri = new StringBuilder("rnuiexplorer://example/") + .append(bundle.getString(PARAM_ROUTE)) + .append("Example") + .toString(); + mInitialProps = new Bundle(); + mInitialProps.putString("exampleFromAppetizeParams", routeUri); + } + super.onCreate(savedInstanceState); + } + + @Override + protected Bundle getLaunchOptions() { + return mInitialProps; + } + @Override protected String getMainComponentName() { return "UIExplorerApp"; diff --git a/Libraries/NavigationExperimental/NavigationRootContainer.js b/Libraries/NavigationExperimental/NavigationRootContainer.js index 2323fda0c37..e15a7b9ea12 100644 --- a/Libraries/NavigationExperimental/NavigationRootContainer.js +++ b/Libraries/NavigationExperimental/NavigationRootContainer.js @@ -41,7 +41,7 @@ type Props = { * events, and use this mapper to convert URIs into actions that your app can * handle */ - linkingActionMap: ?((uri: string) => NavigationAction), + linkingActionMap: ?((uri: ?string) => NavigationAction), /* * Provide this key, and the container will store the navigation state in @@ -113,7 +113,7 @@ class NavigationRootContainer extends React.Component { } componentDidMount(): void { - if (this.props.LinkingActionMap) { + if (this.props.linkingActionMap) { Linking.getInitialURL().then(this._handleOpenURL.bind(this)); Platform.OS === 'ios' && Linking.addEventListener('url', this._handleOpenURLEvent); } @@ -143,10 +143,10 @@ class NavigationRootContainer extends React.Component { } _handleOpenURL(url: ?string): void { - if (!this.props.LinkingActionMap) { + if (!this.props.linkingActionMap) { return; } - const action = this.props.LinkingActionMap(url); + const action = this.props.linkingActionMap(url); if (action) { this.handleNavigation(action); } diff --git a/website/layout/AutodocsLayout.js b/website/layout/AutodocsLayout.js index e48212e586d..b73b54a0728 100644 --- a/website/layout/AutodocsLayout.js +++ b/website/layout/AutodocsLayout.js @@ -412,13 +412,17 @@ var EmbeddedSimulator = React.createClass({ var metadata = this.props.metadata; + var imagePreview = metadata.platform === 'android' + ? Run example in simulator + : Run example in simulator; + return (

Run this example

- Run example in simulator + {imagePreview}
- +
); } @@ -426,9 +430,12 @@ var EmbeddedSimulator = React.createClass({ var Modal = React.createClass({ render: function() { - var appParams = {route: 'AlertIOS'}; + var metadata = this.props.metadata; + var appParams = {route: metadata.title}; var encodedParams = encodeURIComponent(JSON.stringify(appParams)); - var url = `https://appetize.io/embed/bypdk4jnjra5uwyj2kzd2aenv4?device=iphone5s&scale=70&autoplay=false&orientation=portrait&deviceColor=white¶ms=${encodedParams}`; + var url = metadata.platform === 'android' + ? `https://appetize.io/embed/q7wkvt42v6bkr0pzt1n0gmbwfr?device=nexus5&scale=65&autoplay=false&orientation=portrait&osVersion=6.0&deviceColor=white¶ms=${encodedParams}` + : `https://appetize.io/embed/7vdfm9h3e6vuf4gfdm7r5rgc48?device=iphone6s&scale=60&autoplay=false&orientation=portrait&osVersion=9.2&deviceColor=white¶ms=${encodedParams}`; return (
diff --git a/website/server/extractDocs.js b/website/server/extractDocs.js index 782d006fbe6..355ca38f5b1 100644 --- a/website/server/extractDocs.js +++ b/website/server/extractDocs.js @@ -70,12 +70,15 @@ function getExample(componentName, componentPlatform) { // Determines whether a component should have a link to a runnable example -function isRunnable(componentName) { - if (componentName === 'AlertIOS') { - return true; +function isRunnable(componentName, componentPlatform) { + var path = '../Examples/UIExplorer/' + componentName + 'Example.js'; + if (!fs.existsSync(path)) { + path = '../Examples/UIExplorer/' + componentName + 'Example.'+ componentPlatform +'.js'; + if (!fs.existsSync(path)) { + return false; + } } - - return false; + return true; } // Hide a component from the sidebar by making it return false from @@ -136,7 +139,7 @@ function componentsToMarkdown(type, json, filepath, i, styles) { 'platform: ' + componentPlatform, 'next: ' + next, 'sidebar: ' + shouldDisplayInSidebar(componentName), - 'runnable:' + isRunnable(componentName), + 'runnable:' + isRunnable(componentName, componentPlatform), 'path:' + json.filepath, '---', JSON.stringify(json, null, 2), diff --git a/website/src/react-native/css/react-native.css b/website/src/react-native/css/react-native.css index d61d0a695fb..6ccd25a4e09 100644 --- a/website/src/react-native/css/react-native.css +++ b/website/src/react-native/css/react-native.css @@ -973,7 +973,6 @@ small code, li code, p code { } .modal-button-open-img { - background: #05A5D1; height: 358px; } diff --git a/website/src/react-native/img/uiexplorer_main_android.png b/website/src/react-native/img/uiexplorer_main_android.png new file mode 100644 index 00000000000..d510e7aded3 Binary files /dev/null and b/website/src/react-native/img/uiexplorer_main_android.png differ diff --git a/website/src/react-native/img/uiexplorer_main_ios.png b/website/src/react-native/img/uiexplorer_main_ios.png new file mode 100644 index 00000000000..2274ef2dfb4 Binary files /dev/null and b/website/src/react-native/img/uiexplorer_main_ios.png differ