Skip to content

Commit b6be774

Browse files
author
Alex Lavrov
committed
Add propTypes, fix cross-platform menu, refactor/rename some components
1 parent f5b3618 commit b6be774

11 files changed

+136
-97
lines changed

App.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Project from './containers/Project'
66
import Note from './containers/Note'
77
import { store } from './redux/store'
88

9-
const RootStack = createStackNavigator({
9+
const Navigator = createStackNavigator({
1010
Projects: {
1111
screen: Projects
1212
},
@@ -30,7 +30,7 @@ export default class App extends Component {
3030
render() {
3131
return (
3232
<Provider store={store}>
33-
<RootStack/>
33+
<Navigator />
3434
</Provider>
3535
)
3636
}

components/Buttons.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class SaveButton extends PureComponent {
5555
}
5656
}
5757

58-
export class MoreButton extends PureComponent {
58+
export class MenuButton extends PureComponent {
5959
render() {
6060
const { style, onPress } = this.props
6161
return (

components/NoteDetail.js

+7-25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React, { PureComponent } from 'react';
2-
import { StyleSheet, TextInput, Keyboard, View } from 'react-native';
1+
import React, { PureComponent } from 'react'
2+
import PropTypes from 'prop-types'
3+
import { StyleSheet, TextInput, View } from 'react-native'
34

45
const styles = StyleSheet.create({
56
note: {
@@ -15,36 +16,17 @@ const styles = StyleSheet.create({
1516
})
1617

1718
export class NoteDetail extends PureComponent {
18-
state = {
19-
keyboardHeight: 0,
20-
}
21-
22-
componentDidMount () {
23-
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
24-
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
25-
}
26-
27-
componentWillUnmount () {
28-
this.keyboardDidShowListener.remove();
29-
this.keyboardDidHideListener.remove();
30-
}
31-
32-
keyboardDidShow = e => {
33-
this.setState({ keyboardHeight: e.endCoordinates.height })
34-
}
35-
36-
keyboardDidHide = () => {
37-
this.setState({ keyboardHeight: 0 })
19+
static propTypes = {
20+
noteText: PropTypes.string,
21+
onChangeNoteText: PropTypes.func
3822
}
3923

4024
render() {
4125
const { noteText, onChangeNoteText } = this.props
42-
const { keyboardHeight } = this.state
43-
4426
return (
4527
<View style={styles.note}>
4628
<TextInput
47-
style={[styles.noteText, { paddingBottom: keyboardHeight } ]}
29+
style={styles.noteText}
4830
multiline
4931
value={noteText}
5032
placeholder="Type note text here ..."

components/NoteList.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types'
3+
import { NoteType } from './propTypes'
34
import { Alert, View, SwipeableFlatList } from 'react-native';
45
import { NoteListItem } from './NoteListItem'
56
import { RemoveButton } from './Buttons'
67
import { MAX_SWIPE_DISTANCE } from "../constants";
78

89
export class NoteList extends Component {
910
static propTypes = {
10-
notes: PropTypes.array,
11+
notes: PropTypes.arrayOf(NoteType),
1112
onRemoveNote: PropTypes.func,
1213
onNavigateNote: PropTypes.func
1314
}
@@ -23,7 +24,7 @@ export class NoteList extends Component {
2324
)
2425
}
2526

26-
renderDeleteButton = ({ item }) => (
27+
renderQuickActions = ({ item }) => (
2728
<View style={{ flex: 1, alignItems: 'flex-end' }}>
2829
<RemoveButton onPress={() => this.onRemoveNote(item.id)} />
2930
</View>
@@ -32,20 +33,21 @@ export class NoteList extends Component {
3233
renderItem = ({ item }) => {
3334
const { onNavigateNote } = this.props
3435
return (
35-
<NoteListItem note={item} onNavigateNote={onNavigateNote} onRemoveNote={this.removeNote} />
36+
<NoteListItem
37+
note={item}
38+
onNavigateNote={onNavigateNote}
39+
onRemoveNote={this.onRemoveNote} />
3640
)
3741
}
3842

3943
render() {
40-
const { notes } = this.props
41-
4244
return (
4345
<SwipeableFlatList
44-
data={notes}
46+
data={this.props.notes}
4547
bounceFirstRowOnMount={false}
4648
keyExtractor={item => item.id}
4749
maxSwipeDistance={MAX_SWIPE_DISTANCE}
48-
renderQuickActions={this.renderDeleteButton}
50+
renderQuickActions={this.renderQuickActions}
4951
renderItem={this.renderItem}
5052
/>
5153
)

components/NoteListItem.js

+41-24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types'
3-
import { StyleSheet, Image, Text, View, Platform, ActionSheetIOS, UIManager, findNodeHandle } from 'react-native';
4-
import { MoreButton } from './Buttons'
3+
import { NoteType } from './propTypes'
4+
import {
5+
StyleSheet,
6+
Image,
7+
Text,
8+
View,
9+
Platform,
10+
ActionSheetIOS,
11+
UIManager,
12+
findNodeHandle
13+
} from 'react-native';
14+
import { MenuButton } from './Buttons'
15+
import { MAX_NOTE_HEIGHT, NOTE_AVATAR_SIZE } from '../constants'
516

617
const styles = StyleSheet.create({
718
note: {
@@ -10,7 +21,7 @@ const styles = StyleSheet.create({
1021
borderColor: 'gray',
1122
paddingVertical: 20,
1223
paddingHorizontal: 15,
13-
maxHeight: 150
24+
maxHeight: MAX_NOTE_HEIGHT
1425
},
1526

1627
title: {
@@ -20,9 +31,9 @@ const styles = StyleSheet.create({
2031
},
2132

2233
avatar: {
23-
width: 50,
24-
height: 50,
25-
borderRadius: 25
34+
width: NOTE_AVATAR_SIZE,
35+
height: NOTE_AVATAR_SIZE,
36+
borderRadius: NOTE_AVATAR_SIZE / 2
2637
},
2738

2839
info: {
@@ -46,13 +57,7 @@ const styles = StyleSheet.create({
4657

4758
export class NoteListItem extends Component {
4859
static propTypes = {
49-
note: PropTypes.shape({
50-
userName: PropTypes.string,
51-
avatar: PropTypes.any,
52-
editTime: PropTypes.string,
53-
text: PropTypes.string
54-
}),
55-
60+
note: NoteType,
5661
onRemoveNote: PropTypes.func,
5762
onNavigateNote: PropTypes.func,
5863
}
@@ -67,22 +72,30 @@ export class NoteListItem extends Component {
6772
}
6873
}
6974

70-
showActionSheet = options => {
71-
ActionSheetIOS.showActionSheetWithOptions({ options, destructiveButtonIndex: 1 }, this.onPressMenu)
75+
showActionSheet = () => {
76+
ActionSheetIOS.showActionSheetWithOptions({
77+
options: [ 'Edit', 'Delete', 'Cancel' ],
78+
destructiveButtonIndex: 1,
79+
cancelButtonIndex: 2
80+
},
81+
this.onPressMenu
82+
)
7283
}
7384

74-
showPopupMenu = options => {
85+
showPopupMenu = () => {
7586
const button = findNodeHandle(this._buttonRef)
76-
UIManager.showPopupMenu(button, options, (e) => console.error(e), (e, i) => this.onPressMenu(i))
87+
UIManager.showPopupMenu(
88+
button,
89+
[ 'Edit', 'Delete' ],
90+
e => console.error(e),
91+
(e, i) => this.onPressMenu(i)
92+
)
7793
}
7894

7995
onOpenMenu = () => {
80-
const options = [ 'Edit', 'Delete' ]
81-
82-
Platform.select({
83-
ios: this.showActionSheet(options),
84-
android: this.showPopupMenu(options)
85-
})
96+
Platform.OS === 'ios' ?
97+
this.showActionSheet() :
98+
this.showPopupMenu()
8699
}
87100

88101
render() {
@@ -98,7 +111,11 @@ export class NoteListItem extends Component {
98111
</View>
99112
</View>
100113
<Text style={styles.name}>{text}</Text>
101-
<MoreButton ref={ref => this._buttonRef = ref} style={styles.button} onPress={this.onOpenMenu} />
114+
<MenuButton
115+
style={styles.button}
116+
ref={ref => this._buttonRef = ref}
117+
onPress={this.onOpenMenu}
118+
/>
102119
</View>
103120
)
104121
}

components/ProjectList.js

+8-30
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,15 @@
11
import React, { PureComponent } from 'react';
2-
import { StyleSheet, FlatList, TouchableOpacity, Text, View } from 'react-native';
2+
import PropTypes from 'prop-types'
3+
import { ProjectsType } from './propTypes'
4+
import { FlatList } from 'react-native';
5+
import { ProjectListItem } from './ProjectListItem'
36

4-
const styles = StyleSheet.create({
5-
project: {
6-
backgroundColor: 'white',
7-
paddingVertical: 30,
8-
paddingHorizontal: 15,
9-
borderBottomWidth: StyleSheet.hairlineWidth,
10-
borderColor: 'gray'
11-
},
12-
name: {
13-
fontSize: 16
14-
}
15-
})
16-
17-
export class ProjectListItem extends PureComponent {
18-
onPressProject = () => {
19-
const { project, onPressProject } = this.props
20-
onPressProject(project)
21-
}
22-
23-
render() {
24-
return (
25-
<TouchableOpacity onPress={this.onPressProject}>
26-
<View style={styles.project}>
27-
<Text style={styles.name}>{this.props.project.name}</Text>
28-
</View>
29-
</TouchableOpacity>
30-
)
7+
export class ProjectList extends PureComponent {
8+
static propTypes = {
9+
projects: ProjectsType,
10+
onPressProject: PropTypes.func
3111
}
32-
}
3312

34-
export class ProjectList extends PureComponent {
3513
renderItem = ({ item }) => (
3614
<ProjectListItem
3715
project={item}

components/ProjectListItem.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React, { PureComponent } from 'react'
2+
import PropTypes from 'prop-types'
3+
import { ProjectType } from './propTypes'
4+
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';
5+
6+
const styles = StyleSheet.create({
7+
project: {
8+
paddingVertical: 30,
9+
paddingHorizontal: 15,
10+
backgroundColor: 'white',
11+
borderBottomWidth: StyleSheet.hairlineWidth,
12+
borderColor: 'gray'
13+
},
14+
name: {
15+
fontSize: 16
16+
}
17+
})
18+
19+
export class ProjectListItem extends PureComponent {
20+
static propTypes = {
21+
project: ProjectType,
22+
onPressProject: PropTypes.func
23+
}
24+
25+
onPressProject = () => {
26+
const { project, onPressProject } = this.props
27+
onPressProject(project)
28+
}
29+
30+
render() {
31+
return (
32+
<TouchableOpacity onPress={this.onPressProject}>
33+
<View style={styles.project}>
34+
<Text style={styles.name}>{this.props.project.name}</Text>
35+
</View>
36+
</TouchableOpacity>
37+
)
38+
}
39+
}

components/propTypes.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import PropTypes from 'prop-types'
2+
3+
export const NoteType = PropTypes.shape({
4+
userName: PropTypes.string,
5+
avatar: PropTypes.any,
6+
editTime: PropTypes.string,
7+
text: PropTypes.string
8+
})
9+
10+
export const ProjectType = PropTypes.shape({
11+
name: PropTypes.string,
12+
notes: PropTypes.arrayOf(NoteType)
13+
})
14+
15+
export const ProjectsType = PropTypes.arrayOf(ProjectType)

constants.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
export const MAX_SWIPE_DISTANCE = 60
1+
export const MAX_SWIPE_DISTANCE = 60
2+
export const MAX_NOTE_HEIGHT = 150
3+
export const NOTE_AVATAR_SIZE = 50

containers/Project.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { Component } from 'react'
1+
import React, { PureComponent } from 'react'
22
import shortid from 'shortid'
33
import { NoteList } from '../components/NoteList'
44
import { AddButton } from '../components/Buttons'
@@ -7,7 +7,7 @@ import { connect } from 'react-redux'
77
import { bindActionCreators } from 'redux'
88
import { actions } from '../redux/actions'
99

10-
export class Project extends Component {
10+
export class Project extends PureComponent {
1111
static navigationOptions = ({ navigation }) => ({
1212
title: navigation.getParam('name', ''),
1313
headerRight: (

0 commit comments

Comments
 (0)