Skip to content

Instantly share code, notes, and snippets.

@efstathiosntonas
Created January 11, 2018 14:02
Show Gist options
  • Save efstathiosntonas/0865256fa8e0a97a586a377b52b6fc5e to your computer and use it in GitHub Desktop.
Save efstathiosntonas/0865256fa8e0a97a586a377b52b6fc5e to your computer and use it in GitHub Desktop.
Facebook Ads every X posts in React Native Flatlist
import React, {Component} from 'react';
import {ActivityIndicator, AsyncStorage, Dimensions, FlatList, LayoutAnimation, StyleSheet, Text, TouchableHighlight, TouchableOpacity, View, Alert, Platform} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import {Card, CardImage, CardTitle} from 'react-native-material-cards';
import ActionButton from 'react-native-circular-action-menu';
import ImagePicker from 'react-native-image-crop-picker';
import {MaterialIndicator} from 'react-native-indicators';
import Storage from 'react-native-storage';
import {EventRegister} from 'react-native-event-listeners';
import shortid from 'shortid';
import Orientation from 'react-native-orientation';
import SplashScreen from 'rn-splash-screen';
const storage = new Storage({
size : 1000,
storageBackend: AsyncStorage,
defaultExpires: null,
enableCache : true,
});
import {
// AdSettings,
BannerView} from 'react-native-fbads';
var modCount = 0;
var fbKey = shortid.generate();
if (Platform.OS === 'ios') {
var placementId = 'xxxxxxxxxxx';
var type = 'standard'
} else {
placementId = 'xxxxxxxxxxx';
type = 'standard';
}
class Home extends Component {
constructor(props) {
super(props);
this._keyExtractor = this._keyExtractor.bind(this);
this._renderItem = this._renderItem.bind(this);
this.handleRefresh = this.handleRefresh.bind(this);
this.handleLoadMore = this.handleLoadMore.bind(this);
this.renderFooter = this.renderFooter.bind(this);
this.state = {
labels : [],
page : 1,
take : 10,
fetching : false,
modalVisible : false,
isActionButtonVisible: true,
refreshing : false,
loadingmore : false,
mounting : true,
selectedLanguages : [],
noLabelsAvailable : false,
noMoreData : false,
fbad : true,
fbkey : '',
ads : true,
showFBAds : true,
};
}
_keyExtractor = (item, index) => index;
_showImage = (image, upvotes, id) => {
this.props.navigation.navigate('Image', {image: image, upvotes: upvotes, id: id});
};
_imagePicker = () => {
ImagePicker.openPicker({
width : 768,
height : 1024,
cropping : true,
showCropGuidelines : true,
compressImageQuality: 0.8,
smartAlbums : ['UserLibrary'],
mediaType : 'photo'
}).then(image => {
this.props.navigation.navigate('Upload', image);
}).catch(error => {
if (error.code === 'E_PERMISSION_MISSING') {
Alert.alert('Cannot access images', 'Please allow the app to access your image library in your phone settings');
} else {
console.log(error);
}
});
};
_openCamera = () => {
ImagePicker.openCamera({
width : 768,
height : 1024,
cropping : true,
showCropGuidelines : true,
compressImageQuality: 0.8,
mediaType : 'photo'
}).then(image => {
this.props.navigation.navigate('Upload', image);
}).catch(error => {
if (error.code === 'E_PICKER_NO_CAMERA_PERMISSION') {
Alert.alert('Cannot access camera', 'Please allow the app to access camera in your phone settings');
} else if (error.code === 'E_FAILED_TO_OPEN_CAMERA') {
Alert.alert('Cannot access camera', 'Please allow the app to access camera in your phone settings');
} else {
console.log(error);
}
});
};
_onScroll = (event) => {
fbKey = shortid.generate();
// Simple fade-in / fade-out animation
const CustomLayoutLinear = {
duration: 100,
create : {type: LayoutAnimation.Types.linear, property: LayoutAnimation.Properties.opacity},
update : {type: LayoutAnimation.Types.linear, property: LayoutAnimation.Properties.opacity},
delete : {type: LayoutAnimation.Types.linear, property: LayoutAnimation.Properties.opacity}
};
// Check if the user is scrolling up or down by confronting the new scroll position with your own one
const currentOffset = event.nativeEvent.contentOffset.y;
const direction = (currentOffset > 0 && currentOffset > this._listViewOffset)
? 'down'
: 'up';
// If the user is scrolling down (and the action-button is still visible) hide it
const isActionButtonVisible = direction === 'up';
if (isActionButtonVisible !== this.state.isActionButtonVisible) {
LayoutAnimation.configureNext(CustomLayoutLinear);
this.setState({isActionButtonVisible});
}
// Update your scroll position
this._listViewOffset = currentOffset;
};
_listViewOffset = 0;
componentWillMount() {
storage.load({
key: 'ads'
}).then((value) => {
if (value === false) {
this.setState({
ads : false,
showFBAds: false
});
} else {
this.setState({
ads : true,
showFBAds: true
});
}
}).catch((error) => {
this.setState({
ads : true,
showFBAds: true
});
});
this.listener = EventRegister.addEventListener('languageChange', (data) => {
let result = data.map(function (language) {
return language.value;
});
let languages = result.toString();
this.setState({
selectedLanguages: languages,
labels : []
},
() => {
this.handleRefresh();
});
});
this.adsListener = EventRegister.addEventListener('adsRemoved', (data) => {
if (data === false) {
this.handleRefresh();
}
});
}
componentWillUnmount() {
EventRegister.removeEventListener(this.listener);
EventRegister.removeEventListener(this.adsListener);
}
componentDidUpdate() {
}
componentDidMount() {
storage.load({
key: 'languages'
}).then(value => {
if (!value) {
this.setState({
selectedLanguages: [{'label': 'English', value: 'en'}]
});
storage.save({
key : 'languages',
data: [this.state.selectedLanguages]
});
} else {
let result = value.map(function (language) {
return language.value;
});
let languages = result.toString();
this.setState({
selectedLanguages: languages
});
}
}).catch(error => {
this.setState({
selectedLanguages: 'en'
});
storage.save({
key : 'languages',
data: [this.state.selectedLanguages]
});
}).then(() => this.makeRemoteRequest(true));
if (!this.state.fetching) {
if(Platform.OS === 'android') {
SplashScreen.hide();
}
Orientation.lockToPortrait();
}
};
onBannerAdError = (event) => {
console.log('Ad error :(', event.nativeEvent);
this.setState({fbad: false});
};
makeRemoteRequest = (mounting) => {
if (mounting) {
this.setState({fetching: true});
}
const language = this.state.selectedLanguages.length ? this.state.selectedLanguages : 'en';
const {take, page} = this.state;
const url = `https://www.xxxxxxxxxxx.com/query?take=${take}&page=${page}&languages=${language}`;
fetch(url)
.then(response => response.json())
.then(response => {
if (response.length >= 1) {
this.setState(prevState => ({
labels : page === 1 ? response : [...this.state.labels, ...response],
fetching : false,
refreshing : false,
mounting : false,
noLabelsAvailable: false,
}));
if ((this.state.labels.length - modCount) % 20 === 0) {
var fbkey = shortid.generate();
this.state.labels.push({key: fbkey, type: 'ad'});
modCount++;
}
}
else if (response.length < 1 && this.state.labels.length < 1) {
this.setState({
noLabelsAvailable: true,
labels : [],
fetching : false,
loadingmore : false
});
}
else if (response.length = this.state.labels.length) {
this.setState({
noMoreData : true,
fetching : false,
refreshing : false,
loadingmore: false
});
}
})
.catch(error => {
console.log(error);
this.setState({fetching: false});
});
};
handleRefresh = () => {
this.setState({page: 1, take: this.state.take},
() => {
this.makeRemoteRequest();
});
modCount = 0;
};
handleLoadMore = () => {
// if (!this.onEndReachedCalledDuringMomentum) {
this.setState({
page : this.state.page + 1,
loadingmore: true
},
() => {
this.makeRemoteRequest();
});
// this.onEndReachedCalledDuringMomentum = true;
// }
};
renderFooter = () => {
if (!this.state.loadingmore) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth : 1,
borderColor : '#CED0CE'
}}
>
<ActivityIndicator animating size="small"/>
</View>
);
};
_renderItem = ({item}) => {
switch (item.type) {
case 'label':
return <Card style={styles.card}>
<CardTitle title={item.description}/>
<TouchableOpacity style={styles.image} onPress={() => this._showImage(item.imagepath, item.upvotes, item._id)} activeOpacity={0.7}>
<CardImage seperator={false} id={item._id} inColumn={false} source={{uri: item.imagepath}}/>
</TouchableOpacity>
</Card>;
break;
case 'ad':
return (this.state.fbad && this.state.ads ?
<View style={styles.fbCard}>
<Text style={styles.cardTitle}>Sponsored</Text>
<BannerView
placementId={placementId}
type={type}
onError={this.onBannerAdError}
onPress={()=> console.log('click')}
/>
</View>
: null );
break;
default:
return null;
}
};
emptyList = () => {
return (this.state.noLabelsAvailable ?
<View>
<Text
style={styles.nolabels}>
No labels available for the selected language(s) or network error
</Text>
<View style={{flexDirection: 'row', justifyContent: 'space-around', alignContent: 'center', paddingLeft: 80, paddingRight: 80, marginBottom: 15}}>
<TouchableHighlight activeOpacity={0.7} underlayColor={'rgba(0,0,0,0)'} style={styles.okButton} onPress={() => {
this.handleRefresh();
}}>
<Text style={{color: 'blue', marginTop: 5}}>Refresh</Text>
</TouchableHighlight>
<TouchableHighlight activeOpacity={0.7} underlayColor={'rgba(0,0,0,0)'} style={styles.okButton} onPress={() => {
this.props.navigation.navigate('Settings');
}}>
<Text style={{color: 'blue', marginTop: 5}}>Settings</Text>
</TouchableHighlight>
</View>
</View>
: false)
};
render() {
return (
<View style={styles.container}>
<View style={styles.view}>
<View>
{this.state.fetching ? <MaterialIndicator color="red" style={styles.spinner} animating={this.state.fetching}/> : false}
<FlatList
data={this.state.labels}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
onScroll={this._onScroll}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.01}
// onMomentumScrollBegin={() => {
// this.onEndReachedCalledDuringMomentum = false;
// }}
removeClippedSubviews={false}
ListEmptyComponent={this.emptyList}
ListFooterComponent={this.renderFooter}
/>
</View>
</View>
<View style={styles.button}>
{this.state.isActionButtonVisible ?
<ActionButton
buttonColor="rgba(231,76,60,1)"
position="right"
radius={80}
size={60}
elevation={5}
zIndex={1000}>
<ActionButton.Item size={55} elevation={5} buttonColor='#1976D2' title="Camera" onPress={() => this._openCamera()}>
<Icon name="ios-camera-outline" style={styles.actionButtonIcon}/>
</ActionButton.Item>
<ActionButton.Item size={55} elevation={5} buttonColor='#1976D2' title="Album" onPress={() => {
}}>
<Icon name="ios-albums-outline" style={styles.actionButtonIcon} onPress={() => this._imagePicker()}/>
</ActionButton.Item>
</ActionButton> : null}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container : {
...Platform.select({
ios : {
marginTop: 20,
},
android: {
marginTop: 0
}
}),
flex : 1,
padding : 0,
backgroundColor: '#f4f4f4'
},
fbCard : {
justifyContent: 'space-between',
marginBottom: 36,
height: 50
},
cardTitle: {
marginBottom: 5,
marginLeft: 5
},
view : {
backgroundColor: '#f4f4f4',
},
nolabels : {
padding: 50
},
button : {
position: 'absolute',
bottom : 20,
right : 20,
...Platform.select({
android: {
height: 200,
width : 200
}
})
},
spinner : {
position: 'absolute',
height : Dimensions.get('window').height,
width : Dimensions.get('window').width,
},
actionButtonIcon: {
fontSize: 30,
height : 36,
color : 'white',
},
actionButton : {
fontSize: 50
},
image : {
width: '100%'
},
votes : {
color : 'black',
fontSize : 18,
padding : 6,
paddingBottom: 8
},
dialogView : {},
dialog : {
padding: 20
},
dialogText : {},
modal2 : {
justifyContent: 'center',
alignItems : 'center',
height : 100,
width : Dimensions.get('window').width / 1.2
},
buttonText : {
padding : 10,
fontSize: 16,
color : 'blue'
},
okButton : {
marginTop : 15,
justifyContent: 'center',
alignSelf : 'stretch',
alignItems : 'center'
},
labelText : {
paddingLeft: 10,
color : 'grey'
},
languagesText : {
paddingLeft: 10,
paddingTop : 10,
color : 'grey'
},
dialogComponent : {
flex: 1
}
});
export default Home;
@perrosnk
Copy link

Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment