Skip to content

Instantly share code, notes, and snippets.

@SamSaffron
Last active August 10, 2016 10:42
Show Gist options
  • Save SamSaffron/e9866eaa6e5ee2e0cfdfaf40758664bf to your computer and use it in GitHub Desktop.
Save SamSaffron/e9866eaa6e5ee2e0cfdfaf40758664bf to your computer and use it in GitHub Desktop.
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, {
Component,
PropTypes
} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
Image,
AsyncStorage,
TouchableHighlight,
Navigator,
ListView,
WebView
} from 'react-native';
var CookieManager = require('react-native-cookies');
class SiteManager extends Component {
static propTypes = {
onChange: PropTypes.func.isRequired,
}
constructor(props) {
super(props);
this.sites = [];
this.load();
}
add(site) {
this.sites.push(site);
save();
}
save() {
AsyncStorage.setItem('@Discourse.sites', JSON.stringify(this.sites));
}
load() {
AsyncStorage.getItem('@Discourse.sites').then((json) => {
if (json) {
this.sites = JSON.parse(json);
this.props.onChange()
}
});
}
}
class Site {
save(){
this._siteManager.save();
}
updateAuthCookie(){
CookieManager.get(this.url, (err, res) => {
console.log('Got cookies for url', res);
});
}
refreshNotificationCounts(){
}
}
class SiteNav extends Component {
onChangeSites(){
}
constructor(props) {
super(props);
this._siteManager = new SiteManager({onChange: onChangeSites});
}
openUrl(navigator, site) {
navigator.push({title: site.url, index: 1, site: site});
}
checkAuth(navigator, site) {
}
render() {
return (
<Navigator
initialRoute={{ title: 'Discourse', index: 0 }}
renderScene={(route, navigator) => {
if(route.index == 0) {
return <HomePage title={route.title}
siteManager={this._siteManager}
onVisitSite={(site)=> this.openUrl(navigator, site)}
/>
} else if(route.index == 1) {
return <WebView source={{uri: route.site.url}}
onLoadEnd={() =>
this.checkAuth(navigator, route.site)}
/>
}
}
}
style={{paddingTop: 20}}
/>
);
}
}
class HomePage extends Component {
static propTypes = {
onVisitSite: PropTypes.func.isRequired,
siteManager: PropTypes.object.isRequired,
}
constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.onChangeSites();
}
onChangeSites() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.props.siteManager.sites)
})
}
parseSite(body,url) {
var titleRegex = /<title>(.*)<\/title>/gi;
var title = titleRegex.exec(body)[1];
var descriptionRegex = /<meta name="description" content="([^"]*)">/;
var description = descriptionRegex.exec(body)[1];
var iconRegex = /<link rel="apple-touch-icon"[^>]*href="([^"]*)">/;
var icon = iconRegex.exec(body)[1];
this.siteManager.add({title, description, icon, url});
}
doSearch(term) {
fetch(term)
.then((resp)=>resp.blob())
.then((blob)=>{
var partial = blob.slice(0,5000);
var reader = new FileReader();
reader.onloadend = () => {
this.parseSite(reader.result,term);
}
reader.readAsText(partial);
})
.catch((e)=>alert(term + " not found! " + e))
}
render() {
return (
<View>
<TextInput
style={styles.term}
placeholder="Add Site"
returnKeyType="search"
keyboardType="url"
autoCapitalize="none"
onChangeText={(search) => this.setState({search})}
onSubmitEditing={()=>this.doSearch(this.state.search)}
/>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) =>
<TouchableHighlight
onPress={()=>this.props.onVisitSite(rowData)}>
<View accessibilityTraits="link" style={styles.row}>
<Image style={styles.icon} source={{uri: rowData.icon}} style={{width: 40, height: 40}} />
<View style={styles.info}>
<Text>
{rowData.description}
</Text>
<Text>
{rowData.url}
</Text>
</View>
</View>
</TouchableHighlight>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
term: {
height: 40,
paddingLeft: 10
},
icon: {
},
info: {
paddingLeft: 10,
},
row: {
flex: 1,
flexDirection: 'row',
paddingLeft: 10,
paddingBottom: 20
},
container: {
paddingTop: 22,
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: '#FFFAFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('discourse_react_native', () => SiteNav);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment