-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.js
211 lines (200 loc) · 6.33 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// The imported items are straightforward. I'm using React Navigation for my navigation needs.
import React, { Component } from 'react';
import {
Text,
View,
Alert,
Image,
Button,
FlatList,
TextInput,
Dimensions,
ScrollView,
StyleSheet,
ActivityIndicator,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import unavailable from './Images/unavailable.jpg';
// MovieSearch is the first screen the user sees, and it holds most of the logic.
class MovieSearch extends Component {
// I need to initialize some elements in the state.
constructor(props) {
super(props);
this.state = { text: '', data: [], loading: false, };
this.handleSubmit = this.handleSubmit.bind(this);
}
// This method is called when the user clicks on a movie from the list.
// It receives a movie object which holds all of the movie's information.
// It calls the navigate method to navigate to the second screen ('MovieInfo').
// The navigate method also passes the movie object to the second screen.
handlePress(movie) {
this.props.navigation.navigate('MovieInfo', movie)
}
// This method is called when the user clicks the search button.
// First it makes sure a previous fetch() request is not in progress, and that the query is valid.
// Next it will make a new fetch() request, and update the data in the state if successful.
handleSubmit() {
if (this.state.loading) {
alert('Please wait...');
}
else if (this.state.text.length < 1) {
alert('Search cannot be empty!');
} else {
this.setState({ data: [], loading: true });
const url = 'https://theimdbapi.org/api/find/movie?title=' + encodeURI(this.state.text);
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
if (responseJson === null || responseJson[0] === null) {
alert('No results found!');
this.setState({ loading: false });
} else {
this.setState({ data: responseJson, loading: false });
}
})
.catch((error) => {
this.setState({ loading: false });
});
}
}
// This is what the user sees in the first screen.
// ActivityIndicator is only visible when the state is loading (that is, when a fetch() request is active).
// I'm using a FlatList to hold my data (ListView is now deprecated).
render() {
return (
<View style={styles.mainContainer}>
<View style={styles.containerOne}>
<TextInput style={styles.textInput} placeholder='Type movie name here' maxLength={40} onChangeText={(text) => this.setState({ text })} />
</View>
<View style={styles.containerOne}>
<Button onPress={this.handleSubmit} title='Search' />
</View>
<View style={styles.containerTwo}>
{this.state.loading && <ActivityIndicator size='large' animating={true} color='black' style={styles.loader} />}
<FlatList
data={this.state.data}
extraData={this.props.data}
renderItem={({ item }) => <Text style={styles.textListItems}
onPress={this.handlePress.bind(this, item)}>{item.title + ' (' + item.year + ')'}</Text>}
keyExtractor={item => item.imdb_id}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
</View>
</View>
);
}
}
// MovieInfo is the second screen. It shows the selected movie's information.
class MovieInfo extends React.Component {
// Notice that the cases where the movie's Poster or Storyline are missing are handled.
render() {
const { state } = this.props.navigation;
return (
<View style={styles.mainContainer}>
<View style={styles.containerOne}>
<Text style={styles.textMovie} numberOfLines={1}>{state.params.title + ' (' + state.params.year + ')'}</Text>
</View>
<View style={styles.containerThree}>
{state.params.poster.thumb == '' && <Image style={styles.imageMovie} source={unavailable} />}
{state.params.poster.thumb !== '' && <Image style={styles.imageMovie} source={{ uri: state.params.poster.thumb }} />}
</View>
<View style={styles.containerFour}>
<ScrollView style={styles.inputText}>
{state.params.storyline == '' && <Text style={styles.textPlot}>(Plot is Missing)</Text>}
{state.params.storyline !== '' && <Text style={styles.textPlot}>{state.params.storyline}</Text>}
</ScrollView>
</View>
</View>
)
}
}
// I'm using a StackNavigator from React Navigation for my navigation needs.
// This is where I announce the different screens and their headers.
const RootNavigator = StackNavigator({
MovieSearch: {
screen: MovieSearch,
navigationOptions: {
headerTitle: 'Movie Search',
headerTitleStyle: { alignSelf: 'center' }
},
},
MovieInfo: {
screen: MovieInfo,
navigationOptions: {
headerTitle: 'Movie Info',
headerTitleStyle: { alignSelf: 'center' },
headerRight: (<View></View>)
},
},
});
// The navigator must be exported.
export default RootNavigator;
// And this is the StyleSheet where I store all of my different styles.
const styles = StyleSheet.create({
mainContainer: {
height: Dimensions.get('window').height,
width: Dimensions.get('window').width,
backgroundColor: '#C0C0C0',
},
containerOne: {
flex: 1,
justifyContent: 'center',
},
containerTwo: {
flex: 8,
},
containerThree: {
flex: 6,
alignItems: 'center',
},
containerFour: {
flex: 4.5,
alignItems: 'center',
},
textInput: {
flex: 1,
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
},
textListItems: {
fontSize: 30,
marginVertical: 15,
color: 'black',
fontWeight: 'bold',
textAlign: 'center',
},
textMovie: {
flex: 1,
fontSize: 30,
marginTop: 10,
color: 'black',
fontWeight: 'bold',
textAlign: 'center',
},
textPlot: {
flex: 1,
fontSize: 20,
color: '#202020',
fontWeight: 'bold',
textAlign: 'center',
},
inputText: {
marginBottom: 100,
marginHorizontal: 5,
},
imageMovie: {
width: 240,
height: 305,
},
separator: {
height: 3,
marginHorizontal: 10,
backgroundColor: 'black',
},
loader: {
position: 'absolute',
alignSelf: 'center',
marginTop: 70,
},
});