diff --git a/src/ActionConst.js b/src/ActionConst.js index 36e8831ce..be07a9627 100644 --- a/src/ActionConst.js +++ b/src/ActionConst.js @@ -9,3 +9,4 @@ export const POP_TO = 'REACT_NATIVE_ROUTER_FLUX_POP_TO'; export const REFRESH = 'REACT_NATIVE_ROUTER_FLUX_REFRESH'; export const RESET = 'REACT_NATIVE_ROUTER_FLUX_RESET'; export const FOCUS = 'REACT_NATIVE_ROUTER_FLUX_FOCUS'; +export const ANDROID_BACK = 'REACT_NATIVE_ROUTER_FLUX_ANDROID_BACK'; diff --git a/src/Actions.js b/src/Actions.js index 1b2568ded..c851bbe3b 100644 --- a/src/Actions.js +++ b/src/Actions.js @@ -22,6 +22,7 @@ export const ActionMap = { reset: ActionConst.RESET, focus: ActionConst.FOCUS, pushOrPop: ActionConst.PUSH_OR_POP, + androidBack: ActionConst.ANDROID_BACK, [ActionConst.JUMP]: ActionConst.JUMP, [ActionConst.PUSH]: ActionConst.PUSH, [ActionConst.REPLACE]: ActionConst.REPLACE, @@ -33,6 +34,7 @@ export const ActionMap = { [ActionConst.RESET]: ActionConst.RESET, [ActionConst.FOCUS]: ActionConst.FOCUS, [ActionConst.PUSH_OR_POP]: ActionConst.PUSH_OR_POP, + [ActionConst.ANDROID_BACK]: ActionConst.ANDROID_BACK, }; function filterParam(data) { @@ -205,6 +207,10 @@ class Actions { return this.callback({ ...filterParam(props), type: ActionConst.FOCUS }); } + androidBack(props = {}) { + return this.callback({ ...filterParam(props), type: ActionConst.ANDROID_BACK }); + } + create(scene:Scene, wrapBy = x => x) { assert(scene, 'root scene should be defined'); const refs = {}; diff --git a/src/Reducer.js b/src/Reducer.js index 8d8b8f258..f62df2b77 100644 --- a/src/Reducer.js +++ b/src/Reducer.js @@ -92,10 +92,6 @@ function inject(state, action, props, scenes) { case ActionConst.BACK_ACTION: { assert(!state.tabs, 'pop() operation cannot be run on tab bar (tabs=true)'); - if (Platform.OS === 'android') { - assert(state.index > 0, 'You are already in the root scene.'); - } - if (state.index === 0) { return state; } @@ -121,6 +117,18 @@ function inject(state, action, props, scenes) { children: refreshTopChild(state.children.slice(0, -1 * popNum), action.refresh), }; } + case ActionConst.ANDROID_BACK: { + if (Platform.OS === 'android') { + assert(state.index > 0, 'You are already in the root scene.'); + } + + return { + ...state, + index: state.index - 1, + from: state.children[state.children.length - 1], + children: refreshTopChild(state.children.slice(0, -1), action.refresh), + }; + } // This action will pop the scene stack and then replace current scene in one go case ActionConst.POP_AND_REPLACE: { assert(!state.tabs, 'pop() operation cannot be run on tab bar (tabs=true)'); @@ -325,6 +333,7 @@ function reducer({ initialState, scenes }) { // set current route for pop action or refresh action if (ActionMap[action.type] === ActionConst.BACK_ACTION || ActionMap[action.type] === ActionConst.BACK || + ActionMap[action.type] === ActionConst.ANDROID_BACK || ActionMap[action.type] === ActionConst.POP_AND_REPLACE || ActionMap[action.type] === ActionConst.REFRESH || ActionMap[action.type] === ActionConst.POP_TO) { @@ -369,6 +378,7 @@ function reducer({ initialState, scenes }) { // recursive pop parent if (ActionMap[action.type] === ActionConst.BACK_ACTION || ActionMap[action.type] === ActionConst.BACK || + ActionMap[action.type] === ActionConst.ANDROID_BACK || ActionMap[action.type] === ActionConst.POP_AND_REPLACE) { const parent = action.parent || state.scenes[action.key].parent; let el = findElement(state, parent, action.type); @@ -391,6 +401,7 @@ function reducer({ initialState, scenes }) { case ActionConst.JUMP: case ActionConst.REPLACE: case ActionConst.RESET: + case ActionConst.ANDROID_BACK: return update(state, action); default: diff --git a/src/Router.js b/src/Router.js index b10595590..76b785132 100644 --- a/src/Router.js +++ b/src/Router.js @@ -76,7 +76,7 @@ class Router extends Component { } try { - Actions.pop(); + Actions.androidBack(); if (onBackAndroid) { onBackAndroid(); }