From 7a09760727dedd3bda1962cdd2cddc98ce28b15b Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Wed, 8 Jun 2016 16:42:12 +0200 Subject: [PATCH 1/8] Create popToParent Action --- src/Actions.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Actions.js b/src/Actions.js index 77a74fab3..cfe51a1c4 100644 --- a/src/Actions.js +++ b/src/Actions.js @@ -13,6 +13,7 @@ export const PUSH_ACTION = 'push'; export const REPLACE_ACTION = 'replace'; export const POP_ACTION2 = 'back'; export const POP_ACTION = 'BackAction'; +export const POP_TO_PARENT_ACTION = 'popToParent'; export const REFRESH_ACTION = 'refresh'; export const RESET_ACTION = 'reset'; export const FOCUS_ACTION = 'focus'; @@ -32,6 +33,7 @@ function filterParam(data) { const reservedKeys = [ POP_ACTION, POP_ACTION2, + POP_TO_PARENT_ACTION, REFRESH_ACTION, REPLACE_ACTION, JUMP_ACTION, @@ -150,6 +152,10 @@ class Actions { return res; } + popToParent(props = {}) { + return this.callback({ ...filterParam(props), type: POP_TO_PARENT_ACTION }); + } + pop(props = {}) { return this.callback({ ...filterParam(props), type: POP_ACTION }); } From 8956fd29b02aac856389e659a47f806386eb7e6c Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Wed, 8 Jun 2016 16:47:24 +0200 Subject: [PATCH 2/8] Handle the popToParent action at the reducer --- src/Reducer.js | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Reducer.js b/src/Reducer.js index 6505f51d4..c2cb07cf5 100644 --- a/src/Reducer.js +++ b/src/Reducer.js @@ -12,6 +12,7 @@ import { PUSH_ACTION, POP_ACTION2, + POP_TO_PARENT_ACTION, JUMP_ACTION, REPLACE_ACTION, RESET_ACTION, @@ -56,18 +57,22 @@ function inject(state, action, props, scenes) { return state; } let ind; + let numPops = 1; switch (action.type) { + case POP_TO_PARENT_ACTION: + numPops = action.numPops; case POP_ACTION2: case POP_ACTION: assert(!state.tabs, 'pop() operation cannot be run on tab bar (tabs=true)'); if (state.index === 0) { return state; } + return { ...state, - index: state.index - 1, + index: state.index - numPops, from: state.children[state.children.length - 1], - children: state.children.slice(0, -1), + children: state.children.slice(0, - numPops), }; case REFRESH_ACTION: return props.base ? @@ -203,13 +208,14 @@ function reducer({ initialState, scenes }) { } else { // set current route for pop action or refresh action if (action.type === POP_ACTION || action.type === POP_ACTION2 || - action.type === REFRESH_ACTION) { + action.type === REFRESH_ACTION || action.type === POP_TO_PARENT_ACTION) { if (!action.key && !action.parent) { action = { ...getCurrent(state), ...action }; } } + // recursive pop parent - if (action.type === POP_ACTION || action.type === POP_ACTION2) { + if (action.type === POP_ACTION || action.type === POP_ACTION2 || action.type === POP_TO_PARENT_ACTION) { const parent = action.parent || state.scenes[action.key].parent; let el = findElement(state, parent, action.type); while (el.parent && (el.children.length <= 1 || el.tabs)) { @@ -218,10 +224,24 @@ function reducer({ initialState, scenes }) { } action.parent = el.sceneKey; } + + // find the index of the parent to be poped to + if(action.type === POP_TO_PARENT_ACTION) { + const parentName = action.data; + assert(parentName, 'Cannot call popToParent() without a parent name'); + + const parentIndex = state.children.findIndex(child => {console.log(child, child.name, parentName, child.name === parentName); return child.name === parentName}); + console.log(parentIndex); + assert(parentIndex > -1, `Scene named "${parentName}" not parent of "${action.name}"`); + + action.numPops = state.index - parentIndex; + } } + switch (action.type) { case POP_ACTION2: case POP_ACTION: + case POP_TO_PARENT_ACTION: case REFRESH_ACTION: case PUSH_ACTION: case JUMP_ACTION: From 5f083cb87128f72e3baac1b02fb3e65d5b98a32c Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Wed, 8 Jun 2016 16:47:24 +0200 Subject: [PATCH 3/8] Handle the popToParent action at the reducer --- src/Reducer.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Reducer.js b/src/Reducer.js index 6505f51d4..bdde6963a 100644 --- a/src/Reducer.js +++ b/src/Reducer.js @@ -12,6 +12,7 @@ import { PUSH_ACTION, POP_ACTION2, + POP_TO_PARENT_ACTION, JUMP_ACTION, REPLACE_ACTION, RESET_ACTION, @@ -56,18 +57,22 @@ function inject(state, action, props, scenes) { return state; } let ind; + let numPops = 1; switch (action.type) { + case POP_TO_PARENT_ACTION: + numPops = action.numPops; case POP_ACTION2: case POP_ACTION: assert(!state.tabs, 'pop() operation cannot be run on tab bar (tabs=true)'); if (state.index === 0) { return state; } + return { ...state, - index: state.index - 1, + index: state.index - numPops, from: state.children[state.children.length - 1], - children: state.children.slice(0, -1), + children: state.children.slice(0, - numPops), }; case REFRESH_ACTION: return props.base ? @@ -203,13 +208,14 @@ function reducer({ initialState, scenes }) { } else { // set current route for pop action or refresh action if (action.type === POP_ACTION || action.type === POP_ACTION2 || - action.type === REFRESH_ACTION) { + action.type === REFRESH_ACTION || action.type === POP_TO_PARENT_ACTION) { if (!action.key && !action.parent) { action = { ...getCurrent(state), ...action }; } } + // recursive pop parent - if (action.type === POP_ACTION || action.type === POP_ACTION2) { + if (action.type === POP_ACTION || action.type === POP_ACTION2 || action.type === POP_TO_PARENT_ACTION) { const parent = action.parent || state.scenes[action.key].parent; let el = findElement(state, parent, action.type); while (el.parent && (el.children.length <= 1 || el.tabs)) { @@ -218,10 +224,23 @@ function reducer({ initialState, scenes }) { } action.parent = el.sceneKey; } + + // find the index of the parent to be poped to + if(action.type === POP_TO_PARENT_ACTION) { + const parentName = action.data; + assert(parentName, 'Cannot call popToParent() without a parent name'); + + const parentIndex = state.children.findIndex(child => child.name === parentName); + assert(parentIndex > -1, `Scene named "${parentName}" not parent of "${action.name}"`); + + action.numPops = state.index - parentIndex; + } } + switch (action.type) { case POP_ACTION2: case POP_ACTION: + case POP_TO_PARENT_ACTION: case REFRESH_ACTION: case PUSH_ACTION: case JUMP_ACTION: From 2d807babe08094d75357ccde0202d23fffee1e1a Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Sun, 12 Jun 2016 20:49:48 +0200 Subject: [PATCH 4/8] Add a login 3 component --- Example/Example.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Example/Example.js b/Example/Example.js index 80a58646a..4cbb5c3ad 100644 --- a/Example/Example.js +++ b/Example/Example.js @@ -4,6 +4,7 @@ import Launch from './components/Launch' import Register from './components/Register' import Login from './components/Login' import Login2 from './components/Login2' +import Login3 from './components/Login3' import {Scene, Reducer, Router, Switch, TabBar, Modal, Schema, Actions} from 'react-native-router-flux' import Error from './components/Error' import Home from './components/Home' @@ -108,6 +109,7 @@ export default class Example extends React.Component { + From 5e45445939848091cac5c9c24d9d40b9ecc1cf65 Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Sun, 12 Jun 2016 20:50:08 +0200 Subject: [PATCH 5/8] Add button that navigate to login 3 from login 2 --- Example/components/Login2.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Example/components/Login2.js b/Example/components/Login2.js index 1af8e908c..9ab61c650 100644 --- a/Example/components/Login2.js +++ b/Example/components/Login2.js @@ -12,14 +12,13 @@ const styles = StyleSheet.create({ }, }); - export default class extends React.Component { render(){ - return ( Login2 page: {this.props.data} + ); } From ebdb8ce9798b7b7733f1da29de8e0511ced599fd Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Sun, 12 Jun 2016 20:50:37 +0200 Subject: [PATCH 6/8] Change name of action to pop_to --- src/Actions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Actions.js b/src/Actions.js index cfe51a1c4..39c86b48f 100644 --- a/src/Actions.js +++ b/src/Actions.js @@ -13,7 +13,7 @@ export const PUSH_ACTION = 'push'; export const REPLACE_ACTION = 'replace'; export const POP_ACTION2 = 'back'; export const POP_ACTION = 'BackAction'; -export const POP_TO_PARENT_ACTION = 'popToParent'; +export const POP_TO = 'popTo'; export const REFRESH_ACTION = 'refresh'; export const RESET_ACTION = 'reset'; export const FOCUS_ACTION = 'focus'; @@ -33,7 +33,7 @@ function filterParam(data) { const reservedKeys = [ POP_ACTION, POP_ACTION2, - POP_TO_PARENT_ACTION, + POP_TO, REFRESH_ACTION, REPLACE_ACTION, JUMP_ACTION, @@ -152,8 +152,8 @@ class Actions { return res; } - popToParent(props = {}) { - return this.callback({ ...filterParam(props), type: POP_TO_PARENT_ACTION }); + popTo(props = {}) { + return this.callback({ ...filterParam(props), type: POP_TO }); } pop(props = {}) { From 78c849e3c83ed1006e4e631f1affdf773cd69236 Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Sun, 12 Jun 2016 20:53:11 +0200 Subject: [PATCH 7/8] Handle pop_to to nodes and components --- src/Reducer.js | 63 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/src/Reducer.js b/src/Reducer.js index bdde6963a..5d9d73b97 100644 --- a/src/Reducer.js +++ b/src/Reducer.js @@ -12,7 +12,7 @@ import { PUSH_ACTION, POP_ACTION2, - POP_TO_PARENT_ACTION, + POP_TO, JUMP_ACTION, REPLACE_ACTION, RESET_ACTION, @@ -57,10 +57,18 @@ function inject(state, action, props, scenes) { return state; } let ind; - let numPops = 1; + switch (action.type) { - case POP_TO_PARENT_ACTION: - numPops = action.numPops; + case POP_TO: { + const targetIndex = action.targetIndex; + + return { + ...state, + index: targetIndex, + children: state.children.slice(0, (targetIndex + 1)), + }; + } + case POP_ACTION2: case POP_ACTION: assert(!state.tabs, 'pop() operation cannot be run on tab bar (tabs=true)'); @@ -70,9 +78,9 @@ function inject(state, action, props, scenes) { return { ...state, - index: state.index - numPops, + index: state.index - 1, from: state.children[state.children.length - 1], - children: state.children.slice(0, - numPops), + children: state.children.slice(0, - 1), }; case REFRESH_ACTION: return props.base ? @@ -208,14 +216,40 @@ function reducer({ initialState, scenes }) { } else { // set current route for pop action or refresh action if (action.type === POP_ACTION || action.type === POP_ACTION2 || - action.type === REFRESH_ACTION || action.type === POP_TO_PARENT_ACTION) { + action.type === REFRESH_ACTION || action.type === POP_TO) { if (!action.key && !action.parent) { action = { ...getCurrent(state), ...action }; } } + // Find the parent and index of the future state + if (action.type === POP_TO) { + const target = action.data; + assert(target, 'PopTo() must be called with scene name'); + + const targetEl = findElement(state, target, action.type); + assert(targetEl, `Cannot find element name named ${target} within current state`); + + // target is a node + let parent = targetEl.sceneKey; + let targetIndex = 0; + + // target is child of a node + if (!targetEl.children) { + const targetParent = findElement(state, targetEl.parent, action.type); + assert(targetParent, `Cannot find parent for target ${target}`); + parent = targetParent.sceneKey; + + targetIndex = targetParent.children.indexOf(targetEl); + assert(targetIndex > -1, `${target} does not belong to ${targetParent.sceneKey}`); + } + + action.parent = parent; + action.targetIndex = targetIndex; + } + // recursive pop parent - if (action.type === POP_ACTION || action.type === POP_ACTION2 || action.type === POP_TO_PARENT_ACTION) { + if (action.type === POP_ACTION || action.type === POP_ACTION2) { const parent = action.parent || state.scenes[action.key].parent; let el = findElement(state, parent, action.type); while (el.parent && (el.children.length <= 1 || el.tabs)) { @@ -224,23 +258,12 @@ function reducer({ initialState, scenes }) { } action.parent = el.sceneKey; } - - // find the index of the parent to be poped to - if(action.type === POP_TO_PARENT_ACTION) { - const parentName = action.data; - assert(parentName, 'Cannot call popToParent() without a parent name'); - - const parentIndex = state.children.findIndex(child => child.name === parentName); - assert(parentIndex > -1, `Scene named "${parentName}" not parent of "${action.name}"`); - - action.numPops = state.index - parentIndex; - } } switch (action.type) { case POP_ACTION2: case POP_ACTION: - case POP_TO_PARENT_ACTION: + case POP_TO: case REFRESH_ACTION: case PUSH_ACTION: case JUMP_ACTION: From c673ed012c9c23608539f86c7367dadff7a9c57f Mon Sep 17 00:00:00 2001 From: Rafael Seemann Date: Sun, 12 Jun 2016 20:53:35 +0200 Subject: [PATCH 8/8] Add Login 3 component with different PopTo examples --- Example/components/Login3.js | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Example/components/Login3.js diff --git a/Example/components/Login3.js b/Example/components/Login3.js new file mode 100644 index 000000000..e3cc4ef8b --- /dev/null +++ b/Example/components/Login3.js @@ -0,0 +1,39 @@ +import React from 'react'; +import {View, Text, StyleSheet} from "react-native"; +import Button from "react-native-button"; +import {Actions} from "react-native-router-flux"; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + alignItems: "center", + backgroundColor: "#F5FCFF", + }, +}); + +const popToRoot = () => { + Actions.popTo("root"); +} + +const popToLogin1 = () => { + Actions.popTo("loginModal"); +} + +const popToLogin2 = () => { + Actions.popTo("loginModal2"); +} + +export default class extends React.Component { + render(){ + return ( + + Login2 page: {this.props.data} + + + + + + ); + } +}