package com.reactnativenavigation.react; import android.app.Activity; import android.content.Intent; import android.view.View; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.ReactContext; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.shell.MainReactPackage; import com.reactnativenavigation.NavigationApplication; import com.reactnativenavigation.bridge.NavigationReactEventEmitter; import com.reactnativenavigation.bridge.NavigationReactPackage; import com.reactnativenavigation.events.EventBus; import com.reactnativenavigation.events.JsDevReloadEvent; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; public class NavigationReactGateway implements ReactGateway { private final ReactNativeHost host; private NavigationReactEventEmitter reactEventEmitter; private JsDevReloadHandler jsDevReloadHandler; public NavigationReactGateway() { host = new ReactNativeHostImpl(); jsDevReloadHandler = new JsDevReloadHandler(); } @Override public void startReactContextOnceInBackgroundAndExecuteJS() { getReactInstanceManager().createReactContextInBackground(); } public boolean isInitialized() { return host.hasInstance() && getReactInstanceManager().getCurrentReactContext() != null; } @Override public boolean hasStartedCreatingContext() { return getReactInstanceManager().hasStartedCreatingInitialContext(); } public ReactContext getReactContext() { return getReactInstanceManager().getCurrentReactContext(); } public NavigationReactEventEmitter getReactEventEmitter() { return reactEventEmitter; } @Override public ReactInstanceManager getReactInstanceManager() { return host.getReactInstanceManager(); } public void onBackPressed() { getReactInstanceManager().onBackPressed(); } public void onDestroyApp() { getReactInstanceManager().onHostDestroy(); host.clear(); } public void onPauseActivity() { getReactInstanceManager().onHostPause(); jsDevReloadHandler.onPauseActivity(); } public void onNewIntent(Intent intent) { getReactInstanceManager().onNewIntent(intent); } @Override public boolean onKeyUp(View currentFocus, int keyCode) { return jsDevReloadHandler.onKeyUp(currentFocus, keyCode); } public void onResumeActivity(Activity activity, DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) { getReactInstanceManager().onHostResume(activity, defaultHardwareBackBtnHandler); jsDevReloadHandler.onResumeActivity(); } public void onActivityResult(int requestCode, int resultCode, Intent data) { Activity currentActivity = getReactInstanceManager().getCurrentReactContext().getCurrentActivity(); getReactInstanceManager().onActivityResult(currentActivity, requestCode, resultCode, data); } public ReactNativeHost getReactNativeHost() { return host; } //TODO temp hack private void onReactContextInitialized() { reactEventEmitter = new NavigationReactEventEmitter(getReactContext()); } private static class ReactNativeHostImpl extends ReactNativeHost implements ReactInstanceManager.ReactInstanceEventListener { ReactNativeHostImpl() { super(NavigationApplication.instance); } @Override public boolean getUseDeveloperSupport() { return NavigationApplication.instance.isDebug(); } @Override protected List<ReactPackage> getPackages() { List<ReactPackage> list = new ArrayList<>(); list.add(new MainReactPackage()); list.add(new NavigationReactPackage()); addAdditionalReactPackagesIfNeeded(list); return list; } private void addAdditionalReactPackagesIfNeeded(List<ReactPackage> list) { List<ReactPackage> additionalReactPackages = NavigationApplication.instance.createAdditionalReactPackages(); if (additionalReactPackages == null) { return; } for (ReactPackage reactPackage : additionalReactPackages) { if (reactPackage instanceof MainReactPackage) throw new RuntimeException("Do not create a new MainReactPackage. This is created for you."); if (reactPackage instanceof NavigationReactPackage) throw new RuntimeException("Do not create a new NavigationReactPackage. This is created for you."); } list.addAll(additionalReactPackages); } @Override protected ReactInstanceManager createReactInstanceManager() { ReactInstanceManager manager = super.createReactInstanceManager(); if (NavigationApplication.instance.isDebug()) { replaceJsDevReloadListener(manager); } manager.addReactInstanceEventListener(this); return manager; } private void replaceJsDevReloadListener(ReactInstanceManager manager) { new JsDevReloadListenerReplacer(manager, new JsDevReloadListenerReplacer.Listener() { @Override public void onJsDevReload() { EventBus.instance.post(new JsDevReloadEvent()); } }).replace(); } @Override public void onReactContextInitialized(ReactContext context) { ((NavigationReactGateway) NavigationApplication.instance.getReactGateway()).onReactContextInitialized(); NavigationApplication.instance.onReactInitialized(context); } @Override public void clear() { getReactInstanceManager().removeReactInstanceEventListener(this); super.clear(); } @Override protected String getJSMainModuleName() { String jsMainModuleName = NavigationApplication.instance.getJSMainModuleName(); if (jsMainModuleName != null) return jsMainModuleName; return super.getJSMainModuleName(); } @Nullable @Override protected String getJSBundleFile() { String jsBundleFile = NavigationApplication.instance.getJSBundleFile(); if (jsBundleFile != null) return jsBundleFile; return super.getJSBundleFile(); } @Nullable @Override protected String getBundleAssetName() { String bundleAssetName = NavigationApplication.instance.getBundleAssetName(); if (bundleAssetName != null) return bundleAssetName; return super.getBundleAssetName(); } } }