diff --git a/.babelrc b/.babelrc index 25c38a4..3dafd64 100644 --- a/.babelrc +++ b/.babelrc @@ -1,7 +1,13 @@ { - "presets": ["react-native"], + "presets": ["module:metro-react-native-babel-preset"], "sourceMaps": "inline", "plugins": [ + [ + '@babel/plugin-proposal-decorators', + { + legacy: true + } + ], [ "module-resolver", { "extensions": [ diff --git a/android/app/build.gradle b/android/app/build.gradle index 89c9eb7..2d987e6 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -114,7 +114,7 @@ android { ndk { abiFilters "armeabi-v7a", "x86" } - missingDimensionStrategy "RNN.reactNativeVersion", "reactNative56" + missingDimensionStrategy "RNN.reactNativeVersion", "reactNative57" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/android/build.gradle b/android/build.gradle index 5c02932..56c18f9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -13,7 +13,7 @@ subprojects { subproject -> android { variantFilter { variant -> def names = variant.flavors*.name - if (names.contains("reactNative51") || names.contains("reactNative55")) { + if (names.contains("reactNative51") || names.contains("reactNative55") || names.contains("reactNative56")) { setIgnore(true) } } diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000..7b1b993 --- /dev/null +++ b/metro.config.js @@ -0,0 +1,11 @@ +const { mergeConfig } = require('metro-config'); +const { DEFAULT } = require('react-native/local-cli/util/Config'); + +const config = { + resolver: { + sourceExts: ['js', 'json', 'ts', 'tsx', 'css'], + }, + transformModulePath: require.resolve('./scripts/transformer.js'), +}; + +module.exports = mergeConfig(DEFAULT, config); diff --git a/package.json b/package.json index 073b79d..d85f57f 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "tslint": "tslint 'src/**/*.ts?(x)'", "precommit": "lint-staged", "prepush": "npm run test", - "prepare": "patch-package" + "prepare": "patch-package && if [ -f ./scripts/postinstall.sh ]; then sh ./scripts/postinstall.sh; fi" }, "lint-staged": { "*.{ts,tsx}": [ @@ -28,21 +28,22 @@ "date-fns": "1.29.0", "jsc-android": "224109.1.0", "lodash": "4.17.10", - "mobx": "5.0.3", - "mobx-react": "5.2.3", - "mobx-state-tree": "3.0.2", + "mobx": "5.1.0", + "mobx-react": "5.2.5", + "mobx-state-tree": "3.2.3", "react": "16.4.2", - "react-native": "0.56.0", - "react-native-code-push": "5.4.1", + "react-native": "0.57.0-rc.3", + "react-native-code-push": "5.4.2", "react-native-config": "0.11.5", - "react-native-fast-image": "4.0.14", + "react-native-fast-image": "5.0.3", "react-native-firebase": "4.3.8", - "react-native-navigation": "2.0.2452", + "react-native-navigation": "2.0.2501", "react-native-sentry": "0.39.0", "react-native-version-number": "0.3.4" }, "devDependencies": { - "@babel/core": "7.0.0-beta.56", + "@babel/core": "7.0.0-rc.3", + "@babel/plugin-proposal-decorators": "7.0.0-rc.3", "@firebase/app-types": "0.3.2", "@types/core-decorators": "^0.20.0", "@types/date-fns": "^2.6.0", @@ -52,20 +53,20 @@ "@types/jest": "23.3.1", "@types/lodash": "4.14.116", "@types/mobx-devtools-mst": "0.9.0", - "@types/react": "16.4.8", - "@types/react-native": "0.56.6", - "@types/react-native-navigation": "1.1.12", + "@types/react": "16.4.12", + "@types/react-native": "0.56.14", + "@types/react-native-navigation": "2.0.0", "@types/react-test-renderer": "16.0.2", "babel-core": "^7.0.0-0", "babel-jest": "23.4.2", "babel-plugin-module-resolver": "3.1.1", "babel-preset-react-native": "5.0.2", - "detox": "8.1.4", - "enzyme": "3.4.0", - "enzyme-adapter-react-16": "1.2.0", + "detox": "8.2.3", + "enzyme": "3.5.0", + "enzyme-adapter-react-16": "1.3.0", "husky": "0.14.3", - "jest": "23.4.2", - "lint-staged": "7.2.0", + "jest": "23.5.0", + "lint-staged": "7.2.2", "mobx-devtools": "0.9.18", "mobx-devtools-mst": "0.9.18", "patch-package": "5.1.1", @@ -76,10 +77,10 @@ "react-native-ueno-css-modules": "1.0.12", "react-test-renderer": "16.4.2", "stylus": "0.54.5", - "ts-jest": "23.1.3", + "ts-jest": "23.1.4", "tslib": "1.9.3", "tslint": "5.11.0", - "tslint-config-airbnb": "5.9.2", + "tslint-config-airbnb": "5.10.0", "tslint-react": "3.6.0", "typescript": "3.0.1" }, diff --git a/patches/detox+8.1.4.patch b/patches/detox+8.2.3.patch similarity index 100% rename from patches/detox+8.1.4.patch rename to patches/detox+8.2.3.patch diff --git a/patches/react-native-navigation+2.0.2501.patch b/patches/react-native-navigation+2.0.2501.patch new file mode 100644 index 0000000..7ce218f --- /dev/null +++ b/patches/react-native-navigation+2.0.2501.patch @@ -0,0 +1,406 @@ +patch-package +--- a/node_modules/react-native-navigation/lib/android/app/build.gradle ++++ b/node_modules/react-native-navigation/lib/android/app/build.gradle +@@ -57,6 +57,9 @@ android { + reactNative56 { + dimension "RNN.reactNativeVersion" + } ++ reactNative57 { ++ dimension "RNN.reactNativeVersion" ++ } + } + } + +similarity index 100% +rename from node_modules/react-native-navigation/lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationReactNativeHost.java +rename to node_modules/react-native-navigation/lib/android/app/src/reactNative55/java/com/reactnativenavigation/react/NavigationReactNativeHost.java +new file mode 100644 +--- /dev/null ++++ b/node_modules/react-native-navigation/lib/android/app/src/reactNative56/java/com/reactnativenavigation/react/NavigationReactNativeHost.java +@@ -0,0 +1,108 @@ ++package com.reactnativenavigation.react; ++ ++import android.app.Application; ++import android.support.annotation.NonNull; ++import android.support.annotation.Nullable; ++ ++import com.facebook.infer.annotation.Assertions; ++import com.facebook.react.ReactInstanceManager; ++import com.facebook.react.ReactInstanceManagerBuilder; ++import com.facebook.react.ReactNativeHost; ++import com.facebook.react.ReactPackage; ++import com.facebook.react.common.LifecycleState; ++import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; ++import com.facebook.react.shell.MainReactPackage; ++import com.reactnativenavigation.NavigationApplication; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++/** ++ * Default implementation of {@link ReactNativeHost} that includes {@link NavigationPackage} ++ * and user-defined additional packages. ++ */ ++public class NavigationReactNativeHost extends ReactNativeHost implements BundleDownloadListenerProvider { ++ ++ private final boolean isDebug; ++ private final List additionalReactPackages; ++ private @Nullable NavigationDevBundleDownloadListener bundleListener; ++ private final DevBundleDownloadListener bundleListenerMediator = new DevBundleDownloadListenerAdapter() { ++ @Override ++ public void onSuccess() { ++ if (bundleListener != null) { ++ bundleListener.onSuccess(); ++ } ++ } ++ }; ++ ++ ++ public NavigationReactNativeHost(NavigationApplication application) { ++ this(application, application.isDebug(), application.createAdditionalReactPackages()); ++ } ++ ++ @SuppressWarnings("WeakerAccess") ++ public NavigationReactNativeHost(Application application, boolean isDebug, final List additionalReactPackages) { ++ super(application); ++ this.isDebug = isDebug; ++ this.additionalReactPackages = additionalReactPackages; ++ } ++ ++ @Override ++ public void setBundleLoaderListener(NavigationDevBundleDownloadListener listener) { ++ bundleListener = listener; ++ } ++ ++ @Override ++ public boolean getUseDeveloperSupport() { ++ return isDebug; ++ } ++ ++ @Override ++ protected List getPackages() { ++ List packages = new ArrayList<>(); ++ boolean hasMainReactPackage = false; ++ packages.add(new NavigationPackage(this)); ++ if (additionalReactPackages != null) { ++ for (ReactPackage p : additionalReactPackages) { ++ if (!(p instanceof NavigationPackage)) { ++ packages.add(p); ++ } ++ if (p instanceof MainReactPackage) hasMainReactPackage = true; ++ } ++ } ++ if (!hasMainReactPackage) { ++ packages.add(new MainReactPackage()); ++ } ++ return packages; ++ } ++ ++ protected ReactInstanceManager createReactInstanceManager() { ++ ReactInstanceManagerBuilder builder = ReactInstanceManager.builder() ++ .setApplication(getApplication()) ++ .setJSMainModulePath(getJSMainModuleName()) ++ .setUseDeveloperSupport(getUseDeveloperSupport()) ++ .setRedBoxHandler(getRedBoxHandler()) ++ .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) ++ .setUIImplementationProvider(getUIImplementationProvider()) ++ .setInitialLifecycleState(LifecycleState.BEFORE_CREATE) ++ .setDevBundleDownloadListener(getDevBundleDownloadListener()); ++ ++ for (ReactPackage reactPackage : getPackages()) { ++ builder.addPackage(reactPackage); ++ } ++ ++ String jsBundleFile = getJSBundleFile(); ++ if (jsBundleFile != null) { ++ builder.setJSBundleFile(jsBundleFile); ++ } else { ++ builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName())); ++ } ++ return builder.build(); ++ } ++ ++ @SuppressWarnings("WeakerAccess") ++ @NonNull ++ protected DevBundleDownloadListener getDevBundleDownloadListener() { ++ return bundleListenerMediator; ++ } ++} +new file mode 100644 +--- /dev/null ++++ b/node_modules/react-native-navigation/lib/android/app/src/reactNative57/java/com/reactnativenavigation/react/DevBundleDownloadListenerAdapter.java +@@ -0,0 +1,28 @@ ++package com.reactnativenavigation.react; ++ ++import com.facebook.react.bridge.NativeDeltaClient; ++import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; ++ ++import javax.annotation.Nullable; ++ ++public class DevBundleDownloadListenerAdapter implements DevBundleDownloadListener, NavigationDevBundleDownloadListener { ++ @Override ++ public void onSuccess(@Nullable NativeDeltaClient nativeDeltaClient) { ++ onSuccess(); ++ } ++ ++ @Override ++ public void onSuccess() { ++ ++ } ++ ++ @Override ++ public void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total) { ++ ++ } ++ ++ @Override ++ public void onFailure(Exception cause) { ++ ++ } ++} +new file mode 100644 +--- /dev/null ++++ b/node_modules/react-native-navigation/lib/android/app/src/reactNative57/java/com/reactnativenavigation/react/JsDevReloadHandlerFacade.java +@@ -0,0 +1,28 @@ ++package com.reactnativenavigation.react; ++ ++import com.facebook.react.bridge.NativeDeltaClient; ++import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; ++ ++import javax.annotation.Nullable; ++ ++public class JsDevReloadHandlerFacade implements DevBundleDownloadListener, NavigationDevBundleDownloadListener { ++ @Override ++ public void onSuccess(@Nullable NativeDeltaClient nativeDeltaClient) { ++ onSuccess(); ++ } ++ ++ @Override ++ public void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total) { ++ ++ } ++ ++ @Override ++ public void onFailure(Exception cause) { ++ ++ } ++ ++ @Override ++ public void onSuccess() { ++ ++ } ++} +new file mode 100644 +--- /dev/null ++++ b/node_modules/react-native-navigation/lib/android/app/src/reactNative57/java/com/reactnativenavigation/react/NavigationReactNativeHost.java +@@ -0,0 +1,107 @@ ++package com.reactnativenavigation.react; ++ ++import android.app.Application; ++import android.support.annotation.NonNull; ++import android.support.annotation.Nullable; ++ ++import com.facebook.infer.annotation.Assertions; ++import com.facebook.react.ReactInstanceManager; ++import com.facebook.react.ReactInstanceManagerBuilder; ++import com.facebook.react.ReactNativeHost; ++import com.facebook.react.ReactPackage; ++import com.facebook.react.common.LifecycleState; ++import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; ++import com.facebook.react.shell.MainReactPackage; ++import com.reactnativenavigation.NavigationApplication; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++/** ++ * Default implementation of {@link ReactNativeHost} that includes {@link NavigationPackage} ++ * and user-defined additional packages. ++ */ ++public class NavigationReactNativeHost extends ReactNativeHost implements BundleDownloadListenerProvider { ++ ++ private final boolean isDebug; ++ private final List additionalReactPackages; ++ private @Nullable NavigationDevBundleDownloadListener bundleListener; ++ private final DevBundleDownloadListener bundleListenerMediator = new DevBundleDownloadListenerAdapter() { ++ @Override ++ public void onSuccess() { ++ if (bundleListener != null) { ++ bundleListener.onSuccess(); ++ } ++ } ++ }; ++ ++ ++ public NavigationReactNativeHost(NavigationApplication application) { ++ this(application, application.isDebug(), application.createAdditionalReactPackages()); ++ } ++ ++ @SuppressWarnings("WeakerAccess") ++ public NavigationReactNativeHost(Application application, boolean isDebug, final List additionalReactPackages) { ++ super(application); ++ this.isDebug = isDebug; ++ this.additionalReactPackages = additionalReactPackages; ++ } ++ ++ @Override ++ public void setBundleLoaderListener(NavigationDevBundleDownloadListener listener) { ++ bundleListener = listener; ++ } ++ ++ @Override ++ public boolean getUseDeveloperSupport() { ++ return isDebug; ++ } ++ ++ @Override ++ protected List getPackages() { ++ List packages = new ArrayList<>(); ++ boolean hasMainReactPackage = false; ++ packages.add(new NavigationPackage(this)); ++ if (additionalReactPackages != null) { ++ for (ReactPackage p : additionalReactPackages) { ++ if (!(p instanceof NavigationPackage)) { ++ packages.add(p); ++ } ++ if (p instanceof MainReactPackage) hasMainReactPackage = true; ++ } ++ } ++ if (!hasMainReactPackage) { ++ packages.add(new MainReactPackage()); ++ } ++ return packages; ++ } ++ ++ protected ReactInstanceManager createReactInstanceManager() { ++ ReactInstanceManagerBuilder builder = ReactInstanceManager.builder() ++ .setApplication(getApplication()) ++ .setJSMainModulePath(getJSMainModuleName()) ++ .setUseDeveloperSupport(getUseDeveloperSupport()) ++ .setRedBoxHandler(getRedBoxHandler()) ++ .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) ++ .setInitialLifecycleState(LifecycleState.BEFORE_CREATE) ++ .setDevBundleDownloadListener(getDevBundleDownloadListener()); ++ ++ for (ReactPackage reactPackage : getPackages()) { ++ builder.addPackage(reactPackage); ++ } ++ ++ String jsBundleFile = getJSBundleFile(); ++ if (jsBundleFile != null) { ++ builder.setJSBundleFile(jsBundleFile); ++ } else { ++ builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName())); ++ } ++ return builder.build(); ++ } ++ ++ @SuppressWarnings("WeakerAccess") ++ @NonNull ++ protected DevBundleDownloadListener getDevBundleDownloadListener() { ++ return bundleListenerMediator; ++ } ++} +new file mode 100644 +--- /dev/null ++++ b/node_modules/react-native-navigation/lib/android/app/src/reactNative57/java/com/reactnativenavigation/react/ReloadHandlerFacade.java +@@ -0,0 +1,25 @@ ++package com.reactnativenavigation.react; ++ ++import com.facebook.react.bridge.NativeDeltaClient; ++import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; ++ ++import javax.annotation.Nullable; ++ ++public abstract class ReloadHandlerFacade implements DevBundleDownloadListener { ++ @Override ++ public void onSuccess(@Nullable NativeDeltaClient nativeDeltaClient) { ++ ++ } ++ ++ @Override ++ public void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total) { ++ ++ } ++ ++ @Override ++ public void onFailure(Exception cause) { ++ ++ } ++ ++ protected abstract void onSuccess(); ++} +new file mode 100644 +--- /dev/null ++++ b/node_modules/react-native-navigation/lib/android/app/src/reactNative57/java/com/reactnativenavigation/react/SyncUiImplementation.java +@@ -0,0 +1,70 @@ ++package com.reactnativenavigation.react; ++ ++import android.support.annotation.Nullable; ++ ++import com.facebook.react.bridge.ReactApplicationContext; ++import com.facebook.react.bridge.ReadableArray; ++import com.facebook.react.bridge.ReadableMap; ++import com.facebook.react.uimanager.ThemedReactContext; ++import com.facebook.react.uimanager.UIImplementation; ++import com.facebook.react.uimanager.UIManagerModule; ++import com.facebook.react.uimanager.ViewManager; ++import com.facebook.react.uimanager.common.MeasureSpecProvider; ++import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout; ++import com.facebook.react.uimanager.events.EventDispatcher; ++ ++import java.util.List; ++ ++@SuppressWarnings("WeakerAccess") ++public class SyncUiImplementation extends UIImplementation { ++ private static final Object lock = new Object(); ++ ++ public SyncUiImplementation(ReactApplicationContext reactContext, List viewManagerList, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) { ++ super(reactContext, viewManagerList, eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs); ++ } ++ ++ public SyncUiImplementation(ReactApplicationContext reactContext, UIManagerModule.ViewManagerResolver viewManagerResolver, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) { ++ super(reactContext, viewManagerResolver, eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs); ++ } ++ ++ @Override ++ public void manageChildren( ++ int viewTag, ++ @Nullable ReadableArray moveFrom, ++ @Nullable ReadableArray moveTo, ++ @Nullable ReadableArray addChildTags, ++ @Nullable ReadableArray addAtIndices, ++ @Nullable ReadableArray removeFrom) { ++ synchronized (lock) { ++ super.manageChildren(viewTag, moveFrom, moveTo, addChildTags, addAtIndices, removeFrom); ++ } ++ } ++ ++ @Override ++ public void setChildren(int viewTag, ReadableArray childrenTags) { ++ synchronized (lock) { ++ super.setChildren(viewTag, childrenTags); ++ } ++ } ++ ++ @Override ++ public void createView(int tag, String className, int rootViewTag, ReadableMap props) { ++ synchronized (lock) { ++ super.createView(tag, className, rootViewTag, props); ++ } ++ } ++ ++ @Override ++ public void removeRootShadowNode(int rootViewTag) { ++ synchronized (lock) { ++ super.removeRootShadowNode(rootViewTag); ++ } ++ } ++ ++ @Override ++ public void registerRootView(T rootView, int tag, ThemedReactContext context) { ++ synchronized (lock) { ++ super.registerRootView(rootView, tag, context); ++ } ++ } ++} diff --git a/rn-cli.config.js b/rn-cli.config.js deleted file mode 100644 index 0af1402..0000000 --- a/rn-cli.config.js +++ /dev/null @@ -1,22 +0,0 @@ -const blacklist = require('metro/src/blacklist') - -module.exports = { - getTransformModulePath() { - return require.resolve('./scripts/transformer.js'); - }, - getSourceExts() { - return [ - 'js', - 'ts', - 'tsx', - 'css', - // 'styl', - // 'scss', - // 'sass', - // 'less', - ]; - }, - getBlacklistRE() { - return blacklist([/react-native\/local-cli\/core\/__fixtures__.*/]) - }, -}; diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh old mode 100644 new mode 100755 index 7fe527d..8822eaa --- a/scripts/postinstall.sh +++ b/scripts/postinstall.sh @@ -1,5 +1,8 @@ ./scripts/build-env.sh +# Meh +rm -rf ./node_modules/react-native-navigation/lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationReactNativeHost.java + # Pod install if [ -z "$TRAVIS" ]; then (cd ios; pod install; cd -) diff --git a/src/components/button/Button.css b/src/components/button/Button.css index 2cad819..24abb64 100644 --- a/src/components/button/Button.css +++ b/src/components/button/Button.css @@ -1,6 +1,6 @@ .button { border-radius: 4px; - background-color: var(--primary-color); + background-color: #eee; } .text { diff --git a/src/components/button/Button.tsx b/src/components/button/Button.tsx index 019d4e6..99b7d20 100644 --- a/src/components/button/Button.tsx +++ b/src/components/button/Button.tsx @@ -7,6 +7,7 @@ import { GestureResponderEvent, Platform, AccessibilityTrait, + ViewStyle, } from 'react-native'; const styles = require('./Button.css'); @@ -15,6 +16,7 @@ interface IProps { title: string; accessibilityLabel?: string; disabled?: boolean; + style?: ViewStyle; hasTVPreferredFocus?: boolean; onPress?: (event: GestureResponderEvent) => void; testID?: string; @@ -27,6 +29,7 @@ export default class Button extends React.Component { title, accessibilityLabel, disabled, + style, onPress, hasTVPreferredFocus, testID, @@ -60,6 +63,7 @@ export default class Button extends React.Component { testID={testID} disabled={disabled} onPress={onPress} + style={style} {...Platform.OS === 'ios' ? { hasTVPreferredFocus } : {}} > diff --git a/src/components/button/__tests__/__snapshots__/Button.spec.tsx.snap b/src/components/button/__tests__/__snapshots__/Button.spec.tsx.snap index ab5d370..f2e0987 100644 --- a/src/components/button/__tests__/__snapshots__/Button.spec.tsx.snap +++ b/src/components/button/__tests__/__snapshots__/Button.spec.tsx.snap @@ -2,12 +2,6 @@ exports[`renders correctly 1`] = ` { + + static get options() { + return { + topBar: { + title: { + text: 'Counter', + }, + }, + }; + } + + componentDidAppear() { + UI.setComponentId(this.props.componentId); + } + + render() { + return ( + + + Counter: {UI.counter} + + +