Skip to content

Commit

Permalink
Upgraded for RN0.40 + added example and clearer doc
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrien Thiery committed Feb 1, 2017
1 parent b63c2c1 commit ed796bb
Show file tree
Hide file tree
Showing 49 changed files with 2,547 additions and 77 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.yml
@@ -0,0 +1,8 @@
extends:
- osedea/react-native

globals:
__DEV__: false

rules:
no-use-before-define: 0
113 changes: 56 additions & 57 deletions Avatar.js
Expand Up @@ -16,12 +16,13 @@ import React, { Component } from 'react';

import {
Image,
NativeModules,
Platform,
StyleSheet,
TouchableWithoutFeedback,
} from 'react-native';

import ImagePicker from 'react-native-image-picker';

const AVATAR_OPTIONS = {
title: 'Pick your image',
cancelButtonTitle: 'Cancel',
Expand Down Expand Up @@ -87,82 +88,39 @@ const styles = StyleSheet.create({
export default class Avatar extends Component {
static propTypes = {
interactive: React.PropTypes.bool,
isRequire: React.PropTypes.bool,
placeholder: React.PropTypes.number,
onChange: React.PropTypes.func, // called on change when interactive is true
onChangeFailed: React.PropTypes.func, // called on change failure when interactive is true
onPress: React.PropTypes.func,
overlayColor: React.PropTypes.string, // On android only, should be the same than the backgroundColor of the surrounding View
pickerOptions: React.PropTypes.object, // TODO: Define better
placeholderSource: React.PropTypes.number,
placeholderURI: React.PropTypes.string,
resizeMode: Image.propTypes.resizeMode,
size: React.PropTypes.oneOf([
'default',
'mini',
'verySmall',
'small',
'medium',
]),
source: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number, // if require
]),
source: Image.propTypes.source,
style: Image.propTypes.style,
// if true, allows to select a new image on Press (if no onPress function is defined)
uri: React.PropTypes.string,
withBorder: React.PropTypes.bool,
};

static defaultProps = {
overlayColor: colors.defaultOverlayColor,
resizeMode: 'cover',
};

constructor(props) {
super(props);

this.placeholder = this.props.placeholder; // This should be an image

this.state = {
source: this.getAppropriateSource(props.source),
};
}

componentWillReceiveProps(nextProps) {
this.setState({
source: this.getAppropriateSource(nextProps.source),
});
}

getAppropriateSource = (source) => {
let appropriateSource = source;

if (!source) {
appropriateSource = this.placeholder;
} else if (!this.props.isRequire) {
appropriateSource = { uri: source };
}

return appropriateSource;
};

getImage = () => (
<Image
style={[
Platform.OS === 'ios'
? {}
: { overlayColor: this.props.overlayColor },
styles.avatar,
styles[`${this.props.size}Avatar`],
this.props.withBorder ? styles.border : {},
this.props.style,
]}
resizeMode={'cover'}
source={this.state.source}
/>
);
state = {};

handleInteractivePress = () => {
NativeModules.ImagePickerManager.showImagePicker(
ImagePicker.showImagePicker(
{
...AVATAR_OPTIONS,
...this.props.pickerOptions
...AVATAR_OPTIONS,
...this.props.pickerOptions,
},
(response) => {
if (response.error) {
Expand Down Expand Up @@ -193,22 +151,63 @@ export default class Avatar extends Component {
);
};

getAppropriateSource = () => {
let source = this.props.source;

if (this.props.uri) {
source = { uri: this.props.uri };
}

if (Platform.OS === 'android' && !source) {
source = this.getPlaceholder();
}

return source;
}

getPlaceholder = () => {
let placeholder = this.props.placeholderSource;

if (!placeholder && this.props.placeholderURI) {
placeholder = { uri: this.props.placeholderURI };
}

return placeholder;
}

renderAvatarImage = () => (
<Image
style={[
Platform.OS === 'ios'
? {}
: { overlayColor: this.props.overlayColor },
styles.avatar,
styles[`${this.props.size}Avatar`],
this.props.withBorder ? styles.border : {},
this.props.style,
]}
defaultSource={this.getPlaceholder()}
resizeMode={this.props.resizeMode}
source={this.state.source || this.getAppropriateSource()}
/>
);

render() {
if (this.props.onPress) {
return (
<TouchableWithoutFeedback onPress={this.props.onPress}>
{this.getImage()}
{this.renderAvatarImage()}
</TouchableWithoutFeedback>
);
}
if (this.props.interactive) {
return (
<TouchableWithoutFeedback onPress={this.handleInteractivePress}>
{this.getImage()}
{this.renderAvatarImage()}
</TouchableWithoutFeedback>
);
}

return this.getImage();
return this.renderAvatarImage();
}
}
43 changes: 27 additions & 16 deletions README.md
@@ -1,6 +1,12 @@
# react-native-interactive-avatar
An avatar allowing you to click on it to change the image

# [Documentation For React-native 0.26.2+ to 0.40](https://github.com/Osedea/react-native-interactive-avatar/tree/b63c2c131d349b0b8377f6770715b6f1f17bebc9)

# For React-native 0.40+

The component might work on older versions

## Example

```
Expand All @@ -24,26 +30,27 @@ export default class Example extends Component {
render() {
<View>
<Avatar
source={'https://media2.giphy.com/media/sbLpwwHlgls8E/giphy.gif'}
uri={'https://media2.giphy.com/media/sbLpwwHlgls8E/giphy.gif'}
size={'default'}
interactive={true}
placeholderSource={require('example/images/placeholder.png')}
interactive
onChange={this.handleImageChange}
/>
<Avatar
source={require('./images/logo-cropped.png')}
isRequire={true}
source={require('example/images/logo.png')}
size={'medium'}
/>
<Avatar
source={require('./images/logo-cropped.png')}
isRequire={true}
source={require('example/images/logo.png')}
size={'small'}
/>
<Avatar
withBorder={true}
placeholder={require('./images/avatar-placeholder.png')}
withBorder
placeholderSource={require('example/images/placeholder.png')}
interactive
style={{
borderColor: '#000000',
borderWidth: 1,
marginLeft: 5,
}}
size={'verySmall'}
Expand All @@ -55,27 +62,31 @@ export default class Example extends Component {

![Example](example.png)

See more in the [Example Project](./example)

## Properties

Property name | Type | Remark
--- | --- | ----
interactive| React.PropTypes.bool | if true, allows to select a new image on Press (if no onPress function is defined)
isRequire| React.PropTypes.bool
onChange| React.PropTypes.func | called on change when interactive is true
onChangeFailed| React.PropTypes.func | called on change failure when interactive is true
onPress| React.PropTypes.func
onPress| React.PropTypes.func |
overlayColor| React.PropTypes.string | On android only, should be the same than the backgroundColor of the surrounding View
size| React.PropTypes.oneOf([ 'default', 'verySmall', 'small', 'medium' ]),
source| React.PropTypes.oneOfType([ <br>React.PropTypes.string,<br> React.PropTypes.number `// if require is used` <br>])
style| Image.propTypes.style
withBorder| React.PropTypes.bool

pickerOptions | ImagePicker.options | See [react-native-image-picker](https://github.com/marcshilling/react-native-image-picker)
placeholderSource | [Image.propTypes.source](https://facebook.github.io/react-native/docs/image.html#source) | A source for the Image that is displayed when `source` and `uri` are empty
placeholderURI | React.PropTypes.string | A **distant** source for the Image that is displayed when `source` and `uri` are empty
size| React.PropTypes.oneOf([ 'default', 'mini', 'verySmall', 'small', 'medium' ]) | A set of sizes that you can set for the Avatar
source| [Image.propTypes.source](https://facebook.github.io/react-native/docs/image.html#source) | The source Image to display
style| Image.propTypes.style | The style of the Image
uri | React.PropTypes.string | A **distant** source to display
withBorder| React.PropTypes.bool | Should it have a border?

This component uses the awesome [react-native-image-picker](https://github.com/marcshilling/react-native-image-picker)

## Installation

```
npm i --save react-native-interactive-avatar react-native-image-picker
rnpm link react-native-image-picker
react-native link react-native-image-picker
```
Binary file modified example.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions example/.babelrc
@@ -0,0 +1,3 @@
{
"presets": ["react-native"]
}
6 changes: 6 additions & 0 deletions example/.buckconfig
@@ -0,0 +1,6 @@

[android]
target = Google Inc.:Google APIs:23

[maven_repositories]
central = https://repo1.maven.org/maven2
44 changes: 44 additions & 0 deletions example/.flowconfig
@@ -0,0 +1,44 @@
[ignore]
; We fork some components by platform
.*/*[.]android.js

; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/

; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*

; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js

[include]

[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/

[options]
module.system=haste

experimental.strict_type_args=true

munge_underscores=true

module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe

suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-6]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-6]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy

unsafe.enable_getters_and_setters=true

[version]
^0.36.0
1 change: 1 addition & 0 deletions example/.gitattributes
@@ -0,0 +1 @@
*.pbxproj -text
53 changes: 53 additions & 0 deletions example/.gitignore
@@ -0,0 +1,53 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml

# node.js
#
node_modules/
npm-debug.log

# BUCK
buck-out/
\.buckd/
android/app/libs
*.keystore

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
1 change: 1 addition & 0 deletions example/.watchmanconfig
@@ -0,0 +1 @@
{}

0 comments on commit ed796bb

Please sign in to comment.