Skip to content

Commit 0bee5a9

Browse files
authored
Merge pull request #1731 from StoDevX/android-↕
Allow Android to scroll the EditHome view (↕)
2 parents da5ae85 + 9ce8268 commit 0bee5a9

File tree

7 files changed

+329
-123
lines changed

7 files changed

+329
-123
lines changed

source/views/components/colors.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const iosGray = silver
2222

2323
export const androidLightBackground = 'rgb(244, 244, 244)'
2424
export const androidSeparator = 'rgb(224, 224, 224)'
25+
export const androidDisabledIcon = 'rgb(224, 224, 224)'
2526
export const androidTextColor = 'rgb(113, 113, 118)'
2627
export const androidTabAccentColor = '#ffeb3b'
2728

source/views/home/edit/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @flow
2+
3+
export {ConnectedEditHomeView} from './list'
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// @flow
2+
3+
import React from 'react'
4+
import {StyleSheet, FlatList} from 'react-native'
5+
6+
import {saveHomescreenOrder} from '../../../flux/parts/homescreen'
7+
import {connect} from 'react-redux'
8+
import * as c from '../../components/colors'
9+
import sortBy from 'lodash/sortBy'
10+
11+
import type {ViewType} from '../../views'
12+
import {allViews} from '../../views'
13+
import {EditHomeRow} from './row'
14+
15+
const styles = StyleSheet.create({
16+
contentContainer: {
17+
backgroundColor: c.androidLightBackground,
18+
paddingTop: 10,
19+
paddingBottom: 20,
20+
},
21+
})
22+
23+
type Props = {
24+
onChangeOrder: (string[]) => any,
25+
order: string[],
26+
}
27+
28+
class EditHomeView extends React.PureComponent<void, Props, void> {
29+
static navigationOptions = {
30+
title: 'Edit Home',
31+
}
32+
33+
handleMoveUp = (currentOrder: string[], viewName: string) => {
34+
const currentIndex = currentOrder.indexOf(viewName)
35+
const newIndex = Math.max(0, currentIndex - 1)
36+
this.onChangeOrder(currentOrder, viewName, newIndex)
37+
}
38+
39+
handleMoveDown = (currentOrder: string[], viewName: string) => {
40+
const currentIndex = currentOrder.indexOf(viewName)
41+
const newIndex = Math.min(currentOrder.length - 1, currentIndex + 1)
42+
this.onChangeOrder(currentOrder, viewName, newIndex)
43+
}
44+
45+
onChangeOrder = (
46+
currentOrder: string[],
47+
viewName: string,
48+
newIndex: number,
49+
) => {
50+
const newOrder = currentOrder.filter(v => v !== viewName)
51+
newOrder.splice(newIndex, 0, viewName)
52+
53+
this.props.onChangeOrder(newOrder)
54+
}
55+
56+
renderItem = ({item}: {item: ViewType}) => {
57+
const index = this.props.order.indexOf(item.view)
58+
const last = this.props.order.length - 1
59+
return (
60+
<EditHomeRow
61+
item={item}
62+
isFirst={index === 0}
63+
isLast={index === last}
64+
order={this.props.order}
65+
onMoveUp={this.handleMoveUp}
66+
onMoveDown={this.handleMoveDown}
67+
/>
68+
)
69+
}
70+
71+
keyExtractor = (item: ViewType) => item.view
72+
73+
render() {
74+
const data = sortBy(allViews, (item: ViewType) =>
75+
this.props.order.indexOf(item.view),
76+
)
77+
78+
return (
79+
<FlatList
80+
contentContainerStyle={styles.contentContainer}
81+
data={data}
82+
keyExtractor={this.keyExtractor}
83+
onChangeOrder={this.onChangeOrder}
84+
renderItem={this.renderItem}
85+
/>
86+
)
87+
}
88+
}
89+
90+
function mapState(state) {
91+
return {order: state.homescreen.order}
92+
}
93+
94+
function mapDispatch(dispatch) {
95+
return {
96+
onChangeOrder: newOrder => dispatch(saveHomescreenOrder(newOrder)),
97+
}
98+
}
99+
100+
export const ConnectedEditHomeView = connect(mapState, mapDispatch)(
101+
EditHomeView,
102+
)

source/views/home/edit/list.ios.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// @flow
2+
3+
import React from 'react'
4+
import {Dimensions, StyleSheet} from 'react-native'
5+
6+
import {saveHomescreenOrder} from '../../../flux/parts/homescreen'
7+
import {connect} from 'react-redux'
8+
import * as c from '../../components/colors'
9+
import fromPairs from 'lodash/fromPairs'
10+
11+
import SortableList from 'react-native-sortable-list'
12+
13+
import type {ViewType} from '../../views'
14+
import {allViews} from '../../views'
15+
import {EditHomeRow} from './row'
16+
17+
const objViews = fromPairs(allViews.map(v => [v.view, v]))
18+
19+
const styles = StyleSheet.create({
20+
contentContainer: {
21+
backgroundColor: c.iosLightBackground,
22+
paddingTop: 10,
23+
paddingBottom: 20,
24+
flexDirection: 'column',
25+
alignItems: 'stretch',
26+
},
27+
})
28+
29+
type Props = {
30+
onSaveOrder: (string[]) => any,
31+
order: string[],
32+
}
33+
34+
type State = {
35+
width: number,
36+
}
37+
38+
class EditHomeView extends React.PureComponent<void, Props, State> {
39+
static navigationOptions = {
40+
title: 'Edit Home',
41+
}
42+
43+
state = {
44+
width: Dimensions.get('window').width,
45+
}
46+
47+
componentWillMount() {
48+
Dimensions.addEventListener('change', this.handleResizeEvent)
49+
}
50+
51+
componentWillUnmount() {
52+
Dimensions.removeEventListener('change', this.handleResizeEvent)
53+
}
54+
55+
handleResizeEvent = event => {
56+
this.setState(() => ({width: event.window.width}))
57+
}
58+
59+
renderRow = ({data, active}: {data: ViewType, active: boolean}) => (
60+
<EditHomeRow data={data} active={active} width={this.state.width} />
61+
)
62+
63+
onChangeOrder = (order: string[]) => this.props.onSaveOrder(order)
64+
65+
render() {
66+
return (
67+
<SortableList
68+
contentContainerStyle={[
69+
styles.contentContainer,
70+
{width: this.state.width},
71+
]}
72+
data={objViews}
73+
order={this.props.order}
74+
onChangeOrder={this.onChangeOrder}
75+
renderRow={this.renderRow}
76+
/>
77+
)
78+
}
79+
}
80+
81+
function mapState(state) {
82+
return {
83+
order: state.homescreen.order,
84+
}
85+
}
86+
87+
function mapDispatch(dispatch) {
88+
return {
89+
onSaveOrder: newOrder => dispatch(saveHomescreenOrder(newOrder)),
90+
}
91+
}
92+
93+
export const ConnectedEditHomeView = connect(mapState, mapDispatch)(
94+
EditHomeView,
95+
)
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// @flow
2+
3+
import React from 'react'
4+
import {View, StyleSheet, Text} from 'react-native'
5+
import EntypoIcon from 'react-native-vector-icons/Entypo'
6+
import IonIcon from 'react-native-vector-icons/Ionicons'
7+
import * as c from '../../components/colors'
8+
import {Touchable} from '../../components/touchable'
9+
import type {ViewType} from '../../views'
10+
11+
const ROW_HORIZONTAL_MARGIN = 15
12+
const styles = StyleSheet.create({
13+
row: {
14+
flex: 1,
15+
flexDirection: 'row',
16+
alignItems: 'center',
17+
backgroundColor: c.white,
18+
19+
marginVertical: 5,
20+
marginHorizontal: ROW_HORIZONTAL_MARGIN,
21+
paddingVertical: 12,
22+
paddingRight: 10,
23+
borderRadius: 4,
24+
elevation: 1,
25+
},
26+
icon: {
27+
paddingHorizontal: 10,
28+
color: c.androidTextColor,
29+
},
30+
disabledIcon: {
31+
color: c.androidDisabledIcon,
32+
},
33+
text: {
34+
flex: 1,
35+
flexShrink: 0,
36+
fontSize: 18,
37+
color: c.black,
38+
},
39+
})
40+
41+
const MenuIcon = ({icon, tint}: {icon: string, tint: string}) => (
42+
<EntypoIcon name={icon} size={32} style={[styles.icon, {color: tint}]} />
43+
)
44+
45+
type Props = {
46+
item: ViewType,
47+
isFirst: boolean,
48+
isLast: boolean,
49+
order: string[],
50+
onMoveUp: (string[], string) => any,
51+
onMoveDown: (string[], string) => any,
52+
}
53+
54+
export class EditHomeRow extends React.PureComponent<void, Props, void> {
55+
onMoveUp = () => {
56+
this.props.onMoveUp(this.props.order, this.props.item.view)
57+
}
58+
59+
onMoveDown = () => {
60+
this.props.onMoveDown(this.props.order, this.props.item.view)
61+
}
62+
63+
render() {
64+
const {item, isFirst, isLast} = this.props
65+
return (
66+
<View style={styles.row}>
67+
<MenuIcon icon={this.props.item.icon} tint={item.tint} />
68+
69+
<Text style={[styles.text, {color: item.tint}]}>{item.title}</Text>
70+
71+
<ArrowIcon dir="up" disabled={isFirst} onPress={this.onMoveUp} />
72+
<ArrowIcon dir="down" disabled={isLast} onPress={this.onMoveDown} />
73+
</View>
74+
)
75+
}
76+
}
77+
78+
type ArrowIconProps = {
79+
dir: 'up' | 'down',
80+
disabled: boolean,
81+
onPress: () => any,
82+
}
83+
const ArrowIcon = ({dir, disabled, onPress}: ArrowIconProps) => {
84+
const icon = `md-arrow-${dir}`
85+
const size = 24
86+
87+
if (disabled) {
88+
return (
89+
<IonIcon
90+
name={icon}
91+
size={size}
92+
style={[styles.icon, styles.disabledIcon]}
93+
/>
94+
)
95+
}
96+
97+
return (
98+
<Touchable borderless={true} onPress={onPress}>
99+
<IonIcon name={icon} size={size} style={styles.icon} />
100+
</Touchable>
101+
)
102+
}

0 commit comments

Comments
 (0)