React Native Redux 3
- Date:
13 Oct 2019
What is the idea?
- Add
Added movieFinder, a function to get movies by parsing XML
Added MovieList, MovieDetail, Episodes Components
- Moved
Moved all styles to a single file
Moved all actions to a single file
- Modified
Modified reducers for Home
functions/movieFinder.js
const parseString = require('react-native-xml2js').parseString
export default function movieFinder(uriPrefix,keyword,callback){
var results=[]
fetchVideos(uriPrefix+"&wd="+keyword,(vids)=>{
vids.forEach((vid)=>{
fetchVideos(uriPrefix+"ac=videolist&ids="+vid.id[0],(vids)=>{
vids[0].dl[0].dd.forEach((dd)=>{
if(dd.$.flag=="ckm3u8"){
var eps=dd._.split("#")
var episodes=[]
eps.forEach((ep)=>{
var episode=ep.split("$")
episodes.push({label:episode[0],uri:episode[1]})
})
var result={
name: vids[0].name[0],
pic: vids[0].pic[0],
episodes:episodes,
}
callback(result)
}
})
})
})
})
}
// ===================================
const fetchVideos=(uri,callback)=>{
console.log(uri)
fetch(uri).then(response=>response.text())
.then((response)=>{
parseString(response,(err,result)=>{
var videos = result.rss.list[0].video
callback(videos)
})
})
}
To use:
const uriPrefix = "https://cj.okzy.tv/inc/api1s.php?"
const keyword = "硅谷"
movieFinder(uriPrefix,keyword,(result)=>{
console.log(result)
})
components/MovieList.js
import React,{Component} from 'react'
import {FlatList,View,Modal,TouchableOpacity,Text} from 'react-native'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import styles from './styles'
import MovieDetail from './MovieDetail'
import {changeMovie} from '../actions/Home'
class MovieList extends Component{
state={modalVisible:false}
flipModal=()=>{
this.setState({modalVisible:!this.state.modalVisible})
}
render(){
return(
<View>
<Modal animationType="slide" transparent={true}
visible={this.state.modalVisible}>
<View style={styles.Modal}>
<TouchableOpacity style={styles.ModalCloseButton}
onPress={()=>this.flipModal()}>
<Text style={styles.TextWhite}>收起</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.ModalItems}
onPress={()=>this.flipModal()}>
<FlatList data={this.props.Home.movies}
style={{backgroundColor:'transparent'}}
renderItem={({item})=>(
<TouchableOpacity style={styles.ModalCloseButton}
onPress={()=>{
this.flipModal()
this.props.changeMovie(item)
}}>
<MovieDetail movie={item}/>
</TouchableOpacity>
)}
keyExtractor={item=>item.name}
/>
</TouchableOpacity>
</View>
</Modal>
<TouchableOpacity style={styles.ModalOpenButton}
onPress={()=>this.flipModal()}>
<Text style={styles.TextWhite}>影视列表</Text>
</TouchableOpacity>
</View>
)
}
}
const mapStateToProps=(state)=>{
const {Home}=state
return {Home}
}
const mapActionToProps=action=>(
bindActionCreators({changeMovie},action)
)
export default connect(mapStateToProps,mapActionToProps)(MovieList)
components/MovieDetail.js
import React,{Component} from 'react'
import {View,Text,Image} from 'react-native'
import styles from './styles'
export default class MovieDetail extends Component{
render(){
return(
<View style={styles.MovieDetailBody}>
<Text style={styles.MovieDetailName}>
{this.props.movie.name}</Text>
<Image style={styles.MovieDetailImage}
source={{uri: this.props.movie.pic}}/>
</View>
)
}
}
components/Episodes.js
import React,{Component} from 'react'
import {FlatList,View,Modal,TouchableOpacity,Text} from 'react-native'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import styles from './styles'
import {changeMovie} from '../actions/Home'
class Episodes extends Component{
state={modalVisible:false}
flipModal=()=>{
this.setState({modalVisible:!this.state.modalVisible})
}
render(){
return(
<View>
<Modal animationType="slide" transparent={true}
visible={this.state.modalVisible}>
<View style={styles.Modal}>
<TouchableOpacity style={styles.ModalCloseButton}
onPress={()=>this.flipModal()}>
<Text style={styles.TextWhite}>收起</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.ModalItems}
onPress={()=>this.flipModal()}>
<FlatList data={this.props.Home.currentMovie.episodes}
style={{backgroundColor:'transparent'}}
renderItem={({item})=>(
<TouchableOpacity style={styles.ModalCloseButton}
onPress={()=>{
this.flipModal()
var currentMovie = this.props.Home.currentMovie
currentMovie.currentEpisode = item
this.props.changeMovie(currentMovie)
}}>
<Text style={styles.TextWhite}>{item.label}</Text>
</TouchableOpacity>
)}
keyExtractor={item=>item.label}
/>
</TouchableOpacity>
</View>
</Modal>
<TouchableOpacity style={styles.ModalOpenButton}
onPress={()=>this.flipModal()}>
<Text style={styles.TextWhite}>选集</Text>
</TouchableOpacity>
</View>
)
}
}
const mapStateToProps=(state)=>{
const {Home}=state
return {Home}
}
const mapActionToProps=action=>(
bindActionCreators({changeMovie},action)
)
export default connect(mapStateToProps,mapActionToProps)(Episodes)
components/styles.js
import {StyleSheet} from 'react-native'
const ButtonCommon={
alignItems:'center',
borderWidth:2,borderRadius:10,borderColor:'white',
//backgroundColor:'black',
margin:2,
padding:2,
}
const TextCommon={
fontSize:18,fontWeight:'bold',
}
export default styles = StyleSheet.create({
Modal:{alignItems:'flex-end',paddingRight:120},
ModalOpenButton:Object.assign({}, ButtonCommon),
ModalCloseButton:Object.assign({}, ButtonCommon),
ModalItems:{backgroundColor:'black'},
MovieDetailBody:{flexDirection:'row-reverse'},
MovieDetailImage:{width:60,height:90},
MovieDetailName:Object.assign({color:'white'}, TextCommon),
TextWhite:Object.assign({color:'white'}, TextCommon),
})
actions/Home.js
export const changeMovie = payload=>({
type: "changeMovie",
payload: payload
})
reducers/Home.js
const movie1 = {
id:214, name: "硅谷第四季", area: "美国", year: 2017,
pic: "https://facebook.github.io/react-native/img/tiny_logo.webp",
currentEpisode: {label:"第01集",uri:"https://youku.com-youku.net/20180604/9320_35c569aa/index.m3u8"},
episodes: [
{label:"第01集",uri:"https://youku.com-youku.net/20180604/9320_35c569aa/index.m3u8"},
{label:"第02集",uri:"https://youku.com-youku.net/20180604/9321_75f7c37c/index.m3u8"},
],
}
const movie2 = {
id:214, name: "硅谷第4季", area: "美国", year: 2017,
pic: "https://facebook.github.io/react-native/img/tiny_logo.webp",
currentEpisode: {label:"第02集",uri:"https://youku.com-youku.net/20180604/9321_75f7c37c/index.m3u8"},
episodes: [
{label:"第01集",uri:"https://youku.com-youku.net/20180604/9320_35c569aa/index.m3u8"},
{label:"第02集",uri:"https://youku.com-youku.net/20180604/9321_75f7c37c/index.m3u8"},
],
}
const initialState = {
currentMovie: movie1,
movies:[movie1, movie2]
}
const HomeReducer = (state=initialState, action)=>{
switch(action.type){
case "changeMovie":
if(action.payload==null){
var randomIndex = Math.floor(Math.random()*state.movies.length)
console.log("changeMovie",randomIndex)
return Object.assign({}, state, {
currentMovie: state.movies[randomIndex]
})
}else{
console.log(action.payload.name)
return Object.assign({}, state, {
currentMovie: action.payload
})
}
default:
return state
}
}
export default HomeReducer