development helper

This commit is contained in:
Farid from Safi
2016-07-29 14:44:21 +02:00
parent 42a3b5950e
commit 8b0809616e
13 changed files with 21 additions and 4 deletions

17
example/README.md Normal file
View File

@@ -0,0 +1,17 @@
## Example App
Normally, after a code change to react-native-gifted-chat src files,
you must remove the node_modules/react-native-gifted-chat directory
and npm install. The react-native packager wont follow symlinks.
To assist development, this command watches and rsyncs changes:
```
npm run sync
```
Leave a terminal open running this command when running the Example
app and making react-native-gifted-chat src changes.
Development helper inspired by [@joenoon](https://github.com/aksonov/react-native-router-flux/commit/ba85007a36b1d317e9114b9cd46086f4aba9d142)

View File

@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"start": "node_modules/react-native/packager/packager.sh",
"sync-rngc": "rm -rf ./node_modules/react-native-gifted-chat; sane '/usr/bin/rsync -v -a --exclude .git --exclude example --exclude node_modules ../ ./node_modules/react-native-gifted-chat/' .. --glob='{**/*.json,**/*.js}'"
"sync": "rm -rf ./node_modules/react-native-gifted-chat; sane '/usr/bin/rsync -v -a --exclude .git --exclude example --exclude node_modules ../ ./node_modules/react-native-gifted-chat/' .. --glob='{**/*.json,**/*.js}'"
},
"dependencies": {
"react": "15.2.1",
@@ -15,6 +15,6 @@
"eslint": "^3.1.1",
"eslint-plugin-react": "^5.2.2",
"eslint-plugin-react-native": "^1.2.0",
"sane": "^1.3.4"
"sane": "^1.4.0"
}
}

View File

@@ -1,16 +0,0 @@
{
"plugins": [
"react",
"react-native"
],
"extends": ["eslint:recommended", "plugin:react/recommended"],
"parserOptions": {
"sourceType": "module",
"ecmaFeatures" : {
experimentalObjectRestSpread: true
}
},
"env": {
"node": true
}
}

View File

@@ -1 +0,0 @@
TODO.md

View File

@@ -1 +0,0 @@
TODO.md

View File

@@ -1,141 +0,0 @@
import React, { Component } from 'react';
import {
Image,
Text,
TouchableOpacity,
View,
} from 'react-native';
// TODO
// 3 words name initials
// handle only alpha numeric chars
class GiftedAvatar extends Component {
setAvatarColor() {
const userName = this.props.user.name || '';
const name = userName.toUpperCase().split(' ');
if (name.length === 1) {
this.avatarName = `${name[0].charAt(0)}`;
} else if (name.length > 1) {
this.avatarName = `${name[0].charAt(0)}${name[1].charAt(0)}`;
} else {
this.avatarName = '';
}
let sumChars = 0;
for(let i = 0; i < userName.length; i++) {
sumChars += userName.charCodeAt(i);
}
// inspired by https://github.com/wbinnssmith/react-user-avatar
// colors from https://flatuicolors.com/
const colors = [
'#2ecc71', // emerald
'#3498db', // peter river
'#8e44ad', // wisteria
'#e67e22', // carrot
'#e74c3c', // alizarin
'#1abc9c', // turquoise
'#2c3e50', // midnight blue
];
this.avatarColor = colors[sumChars % colors.length];
}
renderAvatar() {
if (typeof this.props.user.avatar === 'function') {
return this.props.user.avatar();
} else if (typeof this.props.user.avatar === 'string') {
return (
<Image
source={{uri: this.props.user.avatar}}
style={[defaultStyles.avatarStyle, this.props.avatarStyle]}
/>
);
}
return null;
}
renderInitials() {
return (
<Text style={[defaultStyles.textStyle, this.props.textStyle]}>
{this.avatarName}
</Text>
);
}
render() {
if (!this.props.user.name && !this.props.user.avatar) {
// render placeholder
return (
<View style={[
defaultStyles.avatarStyle,
{backgroundColor: 'transparent'},
this.props.avatarStyle,
]}/>
)
}
if (this.props.user.avatar) {
// disabled={this.props.onPress ? false : true}
return (
<TouchableOpacity
onPress={() => {
const {onPress, ...other} = this.props;
this.props.onPress && this.props.onPress(other);
}}
>
{this.renderAvatar()}
</TouchableOpacity>
);
}
if (!this.avatarColor) {
this.setAvatarColor();
}
// disabled={this.props.onPress ? false : true}
return (
<TouchableOpacity
onPress={() => {
const {onPress, ...other} = this.props;
this.props.onPress && this.props.onPress(other);
}}
style={[
defaultStyles.avatarStyle,
{backgroundColor: this.avatarColor},
this.props.avatarStyle,
]}
>
{this.renderInitials()}
</TouchableOpacity>
);
}
}
GiftedAvatar.defaultProps = {
user: {
name: null,
avatar: null,
},
onPress: null,
avatarStyle: {},
textStyle: {},
};
const defaultStyles = {
avatarStyle: {
justifyContent: 'center',
alignItems: 'center',
width: 40,
height: 40,
borderRadius: 20,
},
textStyle: {
color: '#fff',
fontSize: 16,
backgroundColor: 'transparent',
fontWeight: '100',
},
};
export default GiftedAvatar;

View File

@@ -1,55 +0,0 @@
import React, { Component } from 'react';
import {
ListView,
} from 'react-native';
import ListRow from './ListRow';
export default class List extends Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([]),
};
this.renderRow = this.renderRow.bind(this);
}
componentWillMount() {
this.updateListView(this.props);
}
componentWillReceiveProps(nextProps) {
this.updateListView(nextProps);
}
updateListView(props) {
if (props.rows) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(props.rows),
});
}
}
renderRow(row = {}) {
if (this.props.renderRow) {
return this.props.renderRow(row);
}
return (
<ListRow
primaryText={row.primaryText}
/>
);
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderHeader={this.props.renderHeader}
enableEmptySections={true}
/>
);
}
}

View File

@@ -1,86 +0,0 @@
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
PixelRatio,
TouchableHighlight,
} from 'react-native';
export default class ListRow extends Component {
renderRightIcon() {
if (this.props.rightIcon) {
return (
<View style={styles.iconContainer}>
{this.props.rightIcon()}
</View>
);
}
return null;
}
renderLeftIcon() {
if (this.props.leftIcon) {
return (
<View style={styles.iconContainer}>
{this.props.leftIcon()}
</View>
);
}
return null;
}
render() {
return (
<TouchableHighlight
underlayColor={'#eee'}
onPress={this.props.onPress}
>
<View style={styles.container}>
{this.renderLeftIcon()}
<View style={styles.textContainer}>
<Text style={styles.primaryText}>
{this.props.primaryText}
</Text>
<Text style={styles.secondaryText}>
{this.props.secondaryText}
</Text>
</View>
{this.renderRightIcon()}
</View>
</TouchableHighlight>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
paddingTop: 10,
paddingBottom: 10,
alignItems: 'center',
borderBottomWidth: 1 / PixelRatio.get(),
borderColor: '#F8F8F8',
},
textContainer: {
flex: 1,
},
primaryText: {
fontSize: 12,
marginBottom: 3,
},
secondaryText: {
fontSize: 11,
color: '#8D8D8D',
},
iconContainer: {
height: 30,
width: 30,
borderRadius: 15,
justifyContent: 'center',
alignItems: 'center',
marginLeft: 10,
marginRight: 10,
backgroundColor: '#C4C4C4',
},
});

View File

@@ -1,9 +0,0 @@
import Avatar from './Avatar';
import List from './List';
import ListRow from './ListRow';
export {
Avatar,
List,
ListRow,
};

View File

@@ -1 +0,0 @@
export * from './components/';

View File

@@ -1,16 +0,0 @@
{
"name": "react-native-gifted-material",
"version": "0.1.0",
"description": "Material components",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Farid from Safi",
"license": "MIT",
"devDependencies": {
"eslint": "^3.1.1",
"eslint-plugin-react": "^5.2.2",
"eslint-plugin-react-native": "^1.1.0"
}
}