/*eslint-disable*/ import {Component} from 'react'; import {findNodeHandle} from 'react-native'; import Navigation from './../Navigation'; import Controllers, {Modal, Notification, ScreenUtils} from './controllers'; const React = Controllers.hijackReact(); const { ControllerRegistry, TabBarControllerIOS, NavigationControllerIOS, DrawerControllerIOS } = React; import _ from 'lodash'; import PropRegistry from '../PropRegistry'; async function startTabBasedApp(params) { if (!params.tabs) { console.error('startTabBasedApp(params): params.tabs is required'); return; } const controllerID = _.uniqueId('controllerID'); params.tabs.map(function (tab, index) { const navigatorID = controllerID + '_nav' + index; const screenInstanceID = _.uniqueId('screenInstanceID'); const components = tab.components; if (!tab.screen && !components) { console.error('startTabBasedApp(params): every tab must include a screen property, take a look at tab#' + (index + 1)); return; } if (components) { params.tabs[index].components = components; Object.assign(tab, components[0]); components.shift(); components.forEach(component => { const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(component.screen, screenInstanceID, params); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); const passProps = Object.assign({}, component.passProps); passProps.navigatorID = navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; component.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID: navigatorID, passProps }; component.subtitle = params.subtitle; component.passProps = passProps; component.navigatorStyle = navigatorStyle; savePassProps(component); }); } const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(tab.screen, screenInstanceID, tab); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); tab.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID }; }); const Controller = Controllers.createClass({ render: function () { if (!params.drawer || (!params.drawer.left && !params.drawer.right)) { return this.renderBody(); } else { const navigatorID = controllerID + '_drawer'; const leftScreenId = _.uniqueId('screenInstanceID'); const rightScreenId = _.uniqueId('screenInstanceID') const {navigatorStyle: leftNavigatorStyle} = params.drawer.left ? _mergeScreenSpecificSettings(params.drawer.left.screen, leftScreenId, params.drawer.left) : {}; const {navigatorStyle: rightNavigatorStyle} = params.drawer.right ? _mergeScreenSpecificSettings(params.drawer.right.screen, rightScreenId, params.drawer.right) : {}; return ( {this.renderBody()} ); } }, renderBody: function () { return ( { params.tabs.map(function (tab, index) { return ( ); }) } ); } }); savePassProps(params); _.set(params, 'passProps.timestamp', Date.now()); ControllerRegistry.registerController(controllerID, () => Controller); return await ControllerRegistry.setRootController(controllerID, params.animationType, params.passProps || {}); } async function startSingleScreenApp(params) { const components = params.components; let screen = params.screen; if (!screen && !components) { console.error('startSingleScreenApp(params): params.screen is required'); return; } const controllerID = _.uniqueId('controllerID'); const navigatorID = controllerID + '_nav'; if (components) { screen = components[0]; components.shift(); components.forEach(component => { const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(component.screen, screenInstanceID, params); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); const passProps = Object.assign({}, params.passProps); passProps.navigatorID = navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; component.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID: navigatorID, passProps }; component.subtitle = params.subtitle; component.passProps = passProps; savePassProps(component); }); } if (!screen.screen) { console.error('startSingleScreenApp(params): screen must include a screen property'); return; } const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(screen.screen, screenInstanceID, screen); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); params.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID }; const passProps = { navigatorID: navigatorID, screenInstanceID: screenInstanceID, navigatorEventID: navigatorEventID, ...screen.passProps }; const Controller = Controllers.createClass({ render: function () { if (!params.drawer || (!params.drawer.left && !params.drawer.right)) { return this.renderBody(); } else { const navigatorID = controllerID + '_drawer'; return ( {this.renderBody()} ); } }, renderBody: function () { return ( ); } }); savePassProps(params); ControllerRegistry.registerController(controllerID, () => Controller); return await ControllerRegistry.setRootController(controllerID, params.animationType, params.passProps || {}); } function _mergeScreenSpecificSettings(screenID, screenInstanceID, params) { const screenClass = Navigation.getRegisteredScreen(screenID); if (!screenClass) { console.error('Cannot create screen ' + screenID + '. Are you it was registered with Navigation.registerScreen?'); return; } const navigatorStyle = Object.assign({}, screenClass.navigatorStyle); if (params.navigatorStyle) { Object.assign(navigatorStyle, params.navigatorStyle); } let navigatorEventID = screenInstanceID + '_events'; let navigatorButtons = _.cloneDeep(screenClass.navigatorButtons); if (params.navigatorButtons) { navigatorButtons = _.cloneDeep(params.navigatorButtons); } if (navigatorButtons.leftButtons) { for (let i = 0; i < navigatorButtons.leftButtons.length; i++) { navigatorButtons.leftButtons[i].onPress = navigatorEventID; } } if (navigatorButtons.rightButtons) { for (let i = 0; i < navigatorButtons.rightButtons.length; i++) { navigatorButtons.rightButtons[i].onPress = navigatorEventID; } } return {navigatorStyle, navigatorButtons, navigatorEventID}; } function navigatorPush(navigator, params) { if (!params.screen) { console.error('Navigator.push(params): params.screen is required'); return; } let previewViewID; const screenInstanceID = _.uniqueId('screenInstanceID'); if (params.previewView instanceof Component) { previewViewID = findNodeHandle(params.previewView) } else if (typeof params.previewView === 'number') { previewViewID = params.previewView; } else if (params.previewView) { console.error('Navigator.push(params): params.previewView is not a valid react view'); } const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(params.screen, screenInstanceID, params); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); const passProps = Object.assign({}, params.passProps); passProps.navigatorID = navigator.navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; passProps.previewViewID = previewViewID; passProps.isPreview = !!previewViewID; params.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID: navigator.navigatorID }; savePassProps(params); Controllers.NavigationControllerIOS(navigator.navigatorID).push({ title: params.title, subtitle: params.subtitle, titleImage: params.titleImage, component: params.screen, animated: params.animated, animationType: params.animationType, passProps: passProps, style: navigatorStyle, backButtonTitle: params.backButtonTitle, backButtonHidden: params.backButtonHidden, leftButtons: navigatorButtons.leftButtons, rightButtons: navigatorButtons.rightButtons, previewViewID: previewViewID, previewActions: params.previewActions, previewHeight: params.previewHeight, previewCommit: params.previewCommit, timestamp: Date.now() }); } function navigatorPop(navigator, params) { Controllers.NavigationControllerIOS(navigator.navigatorID).pop({ animated: params.animated, animationType: params.animationType, timestamp: Date.now() }); } function navigatorPopToRoot(navigator, params) { Controllers.NavigationControllerIOS(navigator.navigatorID).popToRoot({ animated: params.animated, animationType: params.animationType }); } function navigatorResetTo(navigator, params) { if (!params.screen) { console.error('Navigator.resetTo(params): params.screen is required'); return; } const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(params.screen, screenInstanceID, params); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); const passProps = Object.assign({}, params.passProps); passProps.navigatorID = navigator.navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; params.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID: navigator.navigatorID }; savePassProps(params); Controllers.NavigationControllerIOS(navigator.navigatorID).resetTo({ title: params.title, subtitle: params.subtitle, titleImage: params.titleImage, component: params.screen, animated: params.animated, animationType: params.animationType, passProps: passProps, style: navigatorStyle, leftButtons: navigatorButtons.leftButtons, rightButtons: navigatorButtons.rightButtons }); } function navigatorSetDrawerEnabled(navigator, params) { const controllerID = navigator.navigatorID.split('_')[0]; Controllers.NavigationControllerIOS(controllerID + '_drawer').setDrawerEnabled(params) } function navigatorSetTitle(navigator, params) { Controllers.NavigationControllerIOS(navigator.navigatorID).setTitle({ title: params.title, subtitle: params.subtitle, titleImage: params.titleImage, style: params.navigatorStyle, isSetSubtitle: false }); } function navigatorSetSubtitle(navigator, params) { Controllers.NavigationControllerIOS(navigator.navigatorID).setTitle({ title: params.title, subtitle: params.subtitle, titleImage: params.titleImage, style: params.navigatorStyle, isSetSubtitle: true }); } function navigatorSetTitleImage(navigator, params) { Controllers.NavigationControllerIOS(navigator.navigatorID).setTitleImage({ titleImage: params.titleImage }); } function navigatorToggleNavBar(navigator, params) { Controllers.NavigationControllerIOS(navigator.navigatorID).setHidden({ hidden: ((params.to === 'hidden') ? true : false), animated: params.animated }); } function navigatorSetStyle(navigator, params) { _saveNavBarComponentProps(params); Controllers.NavigationControllerIOS(navigator.navigatorID).setStyle(params) } function navigatorToggleDrawer(navigator, params) { const controllerID = navigator.navigatorID.split('_')[0]; if (params.to == 'open') { Controllers.DrawerControllerIOS(controllerID + '_drawer').open({ side: params.side, animated: params.animated }); } else if (params.to == 'closed') { Controllers.DrawerControllerIOS(controllerID + '_drawer').close({ side: params.side, animated: params.animated }); } else { Controllers.DrawerControllerIOS(controllerID + '_drawer').toggle({ side: params.side, animated: params.animated }); } } function navigatorToggleTabs(navigator, params) { const controllerID = navigator.navigatorID.split('_')[0]; Controllers.TabBarControllerIOS(controllerID + '_tabs').setHidden({ hidden: params.to == 'hidden', animated: !(params.animated === false) }); } function navigatorSetTabBadge(navigator, params) { const controllerID = navigator.navigatorID.split('_')[0]; if (params.tabIndex || params.tabIndex === 0) { Controllers.TabBarControllerIOS(controllerID + '_tabs').setBadge({ tabIndex: params.tabIndex, badge: params.badge, badgeColor: params.badgeColor }); } else { Controllers.TabBarControllerIOS(controllerID + '_tabs').setBadge({ contentId: navigator.navigatorID, contentType: 'NavigationControllerIOS', badge: params.badge }); } } function navigatorSetTabButton(navigator, params) { const controllerID = navigator.navigatorID.split('_')[0]; if (params.tabIndex || params.tabIndex === 0) { Controllers.TabBarControllerIOS(controllerID + '_tabs').setTabButton({ tabIndex: params.tabIndex, icon: params.icon, selectedIcon: params.selectedIcon, label: params.label, }); } else { Controllers.TabBarControllerIOS(controllerID + '_tabs').setTabButton({ contentId: navigator.navigatorID, contentType: 'NavigationControllerIOS', icon: params.icon, selectedIcon: params.selectedIcon, label: params.label, }); } } function navigatorSwitchToTab(navigator, params) { const controllerID = navigator.navigatorID.split('_')[0]; if (params.tabIndex || params.tabIndex === 0) { Controllers.TabBarControllerIOS(controllerID + '_tabs').switchTo({ tabIndex: params.tabIndex }); } else { Controllers.TabBarControllerIOS(controllerID + '_tabs').switchTo({ contentId: navigator.navigatorID, contentType: 'NavigationControllerIOS' }); } } function navigatorSetButtons(navigator, navigatorEventID, params) { _saveNavigatorButtonsProps(params); if (params.leftButtons) { const buttons = params.leftButtons.slice(); // clone for (let i = 0; i < buttons.length; i++) { buttons[i].onPress = navigatorEventID; } Controllers.NavigationControllerIOS(navigator.navigatorID).setLeftButtons(buttons, params.animated); } if (params.rightButtons) { const buttons = params.rightButtons.slice(); // clone for (let i = 0; i < buttons.length; i++) { buttons[i].onPress = navigatorEventID; } Controllers.NavigationControllerIOS(navigator.navigatorID).setRightButtons(buttons, params.animated); } } function showModal(params) { if (!params.screen) { console.error('showModal(params): params.screen is required'); return; } const controllerID = _.uniqueId('controllerID'); const navigatorID = controllerID + '_nav'; const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(params.screen, screenInstanceID, params); _saveNavigatorButtonsProps(navigatorButtons); _saveNavBarComponentProps(navigatorStyle); const passProps = Object.assign({}, params.passProps); passProps.navigatorID = navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; passProps.timestamp = Date.now(); params.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID: navigator.navigatorID }; const Controller = Controllers.createClass({ render: function () { return ( ); } }); savePassProps(params); ControllerRegistry.registerController(controllerID, () => Controller); Modal.showController(controllerID, params.animationType); } async function dismissModal(params) { return await Modal.dismissController(params.animationType); } async function dismissAllModals(params) { return await Modal.dismissAllControllers(params.animationType); } function showLightBox(params) { if (!params.screen) { console.error('showLightBox(params): params.screen is required'); return; } const controllerID = _.uniqueId('controllerID'); const navigatorID = controllerID + '_nav'; const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(params.screen, screenInstanceID, params); const passProps = Object.assign({}, params.passProps); passProps.navigatorID = navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; params.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID }; savePassProps(params); Modal.showLightBox({ component: params.screen, passProps: passProps, style: params.style }); } function dismissLightBox(params) { Modal.dismissLightBox(); } function showInAppNotification(params) { if (!params.screen) { console.error('showInAppNotification(params): params.screen is required'); return; } const controllerID = _.uniqueId('controllerID'); const navigatorID = controllerID + '_nav'; const screenInstanceID = _.uniqueId('screenInstanceID'); const { navigatorStyle, navigatorButtons, navigatorEventID } = _mergeScreenSpecificSettings(params.screen, screenInstanceID, params); const passProps = Object.assign({}, params.passProps); passProps.navigatorID = navigatorID; passProps.screenInstanceID = screenInstanceID; passProps.navigatorEventID = navigatorEventID; params.navigationParams = { screenInstanceID, navigatorStyle, navigatorButtons, navigatorEventID, navigatorID }; savePassProps(params); let args = { component: params.screen, passProps: passProps, style: params.style, animation: params.animation || Notification.AnimationPresets.default, position: params.position, shadowRadius: params.shadowRadius, dismissWithSwipe: params.dismissWithSwipe || true, autoDismissTimerSec: params.autoDismissTimerSec || 5 }; if (params.autoDismiss === false) delete args.autoDismissTimerSec; Notification.show(args); } function dismissInAppNotification(params) { Notification.dismiss(params); } function savePassProps(params) { //TODO this needs to be handled in a common place, //TODO also, all global passProps should be handled differently if (params.navigationParams && params.passProps) { PropRegistry.save(params.navigationParams.screenInstanceID, params.passProps); } if (params.screen && params.screen.passProps) { PropRegistry.save(params.screen.navigationParams.screenInstanceID, params.screen.passProps); } if (_.get(params, 'screen.topTabs')) { _.forEach(params.screen.topTabs, (tab) => savePassProps(tab)); } if (params.tabs) { _.forEach(params.tabs, (tab) => { if (!tab.passProps) { tab.passProps = params.passProps; } savePassProps(tab); }); } } function showContextualMenu() { // Android only } function dismissContextualMenu() { // Android only } async function getCurrentlyVisibleScreenId() { return await ScreenUtils.getCurrentlyVisibleScreenId(); } function _saveNavBarComponentProps(navigatorStyle) { if (navigatorStyle.navBarCustomViewInitialProps) { const passPropsKey = _.uniqueId('navBarComponent'); PropRegistry.save(passPropsKey, navigatorStyle.navBarCustomViewInitialProps); navigatorStyle.navBarCustomViewInitialProps = {passPropsKey}; } } function _saveNavigatorButtonsProps({rightButtons, leftButtons}) { _saveNavigatorButtonsPassProps(rightButtons); _saveNavigatorButtonsPassProps(leftButtons); } function _saveNavigatorButtonsPassProps(buttons = []) { buttons.forEach((button) => { if (button.component) { const passPropsKey = _.uniqueId('customButtonComponent'); PropRegistry.save(passPropsKey, button.passProps); button.passProps = {passPropsKey}; } }) } async function getLaunchArgs() { return await ControllerRegistry.getLaunchArgs(); } export default { startTabBasedApp, startSingleScreenApp, navigatorPush, navigatorPop, navigatorPopToRoot, navigatorResetTo, showModal, dismissModal, dismissAllModals, showLightBox, dismissLightBox, showInAppNotification, dismissInAppNotification, navigatorSetButtons, navigatorSetDrawerEnabled, navigatorSetTitle, navigatorSetSubtitle, navigatorSetStyle, navigatorSetTitleImage, navigatorToggleDrawer, navigatorToggleTabs, navigatorSetTabBadge, navigatorSetTabButton, navigatorSwitchToTab, navigatorToggleNavBar, showContextualMenu, dismissContextualMenu, getCurrentlyVisibleScreenId, getLaunchArgs };