Skip to content

Commit

Permalink
Rewrite GiftedAvatar class component to functional component + remo…
Browse files Browse the repository at this point in the history
…ve `defaultProps`
  • Loading branch information
danilvalov committed Sep 11, 2024
1 parent 40536ec commit a18e271
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 93 deletions.
2 changes: 1 addition & 1 deletion src/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
View,
ViewStyle,
} from 'react-native'
import GiftedAvatar from './GiftedAvatar'
import { GiftedAvatar } from './GiftedAvatar'
import { StylePropType, isSameUser, isSameDay } from './utils'
import { IMessage, LeftRightStyle, User } from './Models'

Expand Down
178 changes: 87 additions & 91 deletions src/GiftedAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types'
import React from 'react'
import React, { useCallback, useRef } from 'react'
import {
Image,
Text,
Expand Down Expand Up @@ -51,38 +51,32 @@ export interface GiftedAvatarProps {
onLongPress?: (props: GiftedAvatarProps) => void
}

export default class GiftedAvatar extends React.Component<GiftedAvatarProps> {
static defaultProps = {
user: {
export function GiftedAvatar (
props: GiftedAvatarProps
) {
const avatarNameRef = useRef<string | undefined>(undefined)
const avatarColorRef = useRef<string | undefined>(undefined)

const {
user = {
name: null,
avatar: null,
},
onPress: undefined,
onLongPress: undefined,
avatarStyle: {},
textStyle: {},
}

static propTypes = {
user: PropTypes.object,
onPress: PropTypes.func,
onLongPress: PropTypes.func,
avatarStyle: StylePropType,
textStyle: StylePropType,
}

avatarName?: string = undefined
avatarColor?: string = undefined
avatarStyle = {},
textStyle = {},
onPress,
} = props

setAvatarColor () {
const userName = (this.props.user && this.props.user.name) || ''
const setAvatarColor = useCallback(() => {
const userName = user.name || ''
const name = userName.toUpperCase().split(' ')

if (name.length === 1)
this.avatarName = `${name[0].charAt(0)}`
avatarNameRef.current = `${name[0].charAt(0)}`
else if (name.length > 1)
this.avatarName = `${name[0].charAt(0)}${name[1].charAt(0)}`
avatarNameRef.current = `${name[0].charAt(0)}${name[1].charAt(0)}`
else
this.avatarName = ''
avatarNameRef.current = ''

let sumChars = 0
for (let i = 0; i < userName.length; i += 1)
Expand All @@ -100,106 +94,108 @@ export default class GiftedAvatar extends React.Component<GiftedAvatarProps> {
midnightBlue,
]

this.avatarColor = colors[sumChars % colors.length]
}
avatarColorRef.current = colors[sumChars % colors.length]
}, [user.name])

renderAvatar () {
const { user } = this.props
if (user)
if (typeof user.avatar === 'function')
return user.avatar([styles.avatarStyle, this.props.avatarStyle])
else if (typeof user.avatar === 'string')
const renderAvatar = useCallback(() => {
switch (typeof user.avatar) {
case 'function':
return user.avatar([styles.avatarStyle, avatarStyle])
case 'string':
return (
<Image
source={{ uri: user.avatar }}
style={[styles.avatarStyle, this.props.avatarStyle]}
style={[styles.avatarStyle, avatarStyle]}
/>
)
else if (typeof user.avatar === 'number')
case 'number':
return (
<Image
source={user.avatar}
style={[styles.avatarStyle, this.props.avatarStyle]}
style={[styles.avatarStyle, avatarStyle]}
/>
)
default:
return null
}
}, [user.name, user.avatar, avatarStyle])

return null
}

renderInitials () {
const renderInitials = useCallback(() => {
return (
<Text style={[styles.textStyle, this.props.textStyle]}>
{this.avatarName}
<Text style={[styles.textStyle, textStyle]}>
{avatarNameRef.current}
</Text>
)
}
}, [textStyle])

handleOnPress = () => {
const handleOnPress = () => {
const {
/* eslint-disable @typescript-eslint/no-unused-vars */
onPress,
/* eslint-enable @typescript-eslint/no-unused-vars */
...rest
} = this.props
} = props

if (this.props.onPress)
this.props.onPress(rest)
if (onPress)
onPress(rest)
}

handleOnLongPress = () => {
const handleOnLongPress = () => {
const {
/* eslint-disable @typescript-eslint/no-unused-vars */
onLongPress,
/* eslint-enable @typescript-eslint/no-unused-vars */
...rest
} = this.props
} = props

if (this.props.onLongPress)
this.props.onLongPress(rest)
if (onLongPress)
onLongPress(rest)
}

render () {
if (!this.props.user || (!this.props.user.name && !this.props.user.avatar))
// render placeholder
return (
<View
style={[
styles.avatarStyle,
styles.avatarTransparent,
this.props.avatarStyle,
]}
accessibilityRole='image'
/>
)

if (this.props.user.avatar)
return (
<TouchableOpacity
disabled={!this.props.onPress}
onPress={this.handleOnPress}
onLongPress={this.handleOnLongPress}
accessibilityRole='image'
>
{this.renderAvatar()}
</TouchableOpacity>
)

this.setAvatarColor()

if (!user || (!user.name && !user.avatar))
// render placeholder
return (
<TouchableOpacity
disabled={!this.props.onPress}
onPress={this.handleOnPress}
onLongPress={this.handleOnLongPress}
<View
style={[
styles.avatarStyle,
{ backgroundColor: this.avatarColor },
this.props.avatarStyle,
styles.avatarTransparent,
avatarStyle,
]}
accessibilityRole='image'
/>
)

if (user.avatar)
return (
<TouchableOpacity
disabled={!onPress}
onPress={handleOnPress}
onLongPress={handleOnLongPress}
accessibilityRole='image'
>
{this.renderInitials()}
{renderAvatar()}
</TouchableOpacity>
)
}

setAvatarColor()

return (
<TouchableOpacity
disabled={!onPress}
onPress={handleOnPress}
onLongPress={handleOnLongPress}
style={[
styles.avatarStyle,
{ backgroundColor: avatarColorRef.current },
avatarStyle,
]}
accessibilityRole='image'
>
{renderInitials()}
</TouchableOpacity>
)
}

GiftedAvatar.propTypes = {
user: PropTypes.object,
onPress: PropTypes.func,
onLongPress: PropTypes.func,
avatarStyle: StylePropType,
textStyle: StylePropType,
}
2 changes: 1 addition & 1 deletion src/GiftedChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import Bubble from './Bubble'
import { Composer, ComposerProps } from './Composer'
import { MAX_COMPOSER_HEIGHT, MIN_COMPOSER_HEIGHT, TEST_ID } from './Constant'
import { Day, DayProps } from './Day'
import GiftedAvatar from './GiftedAvatar'
import { GiftedAvatar } from './GiftedAvatar'
import { GiftedChatContext } from './GiftedChatContext'
import { InputToolbar, InputToolbarProps } from './InputToolbar'
import { LoadEarlier, LoadEarlierProps } from './LoadEarlier'
Expand Down

0 comments on commit a18e271

Please sign in to comment.