一旦用户激活了 onLongPress={} 功能,我正在尝试通过 renderCustomView={this.displayEmojis} 为单个消息呈现视图。但是,我试图显示的视图会重复屏幕上的每条消息,而不是按下的消息。我附上了当我尝试按下显示多条消息的消息时发生的情况:
//EventPost
import React from 'react'
import { Platform, View, StatusBar, TouchableOpacity, Text, Image, StyleSheet } from 'react-native'
import { getStatusBarHeight } from 'react-native-status-bar-height';
import { GiftedChat } from 'react-native-gifted-chat'
import emojiUtils from 'emoji-utils'
import KeyboardSpacer from 'react-native-keyboard-spacer';
import SlackMessage from './SlackMessage'
import Keyboard from 'react-native';
export default class EventPosts extends React.Component {
constructor(props) {
super(props);
this.state = {
messages: [],
toggle: false,
reactedMessage: 0,
reacted: false,
images: [
require("../assets/emojis/beer_photo.png"),
require("../assets/emojis/party_photo.png"),
require("../assets/emojis/laughing-emoji_photo.png"),
require("../assets/emojis/happy_photo.png"),
require("../assets/emojis/crying_photo.png"),
],
id: 0,
}
this.displayEmojis = this.displayEmojis.bind(this);
}
componentDidMount() {
this.setState({
messages: [
{
_id: 1,
text: 'I cant wait for this birthday party',
createdAt: new Date(),
user: {
_id: 2,
name: 'Andrew Garrett',
avatar: 'https://placeimg.com/140/140/any',
},
},
],
});
}
onSend(messages = []) {
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages),
}))
}
renderMessage(props) {
const {
currentMessage: { text: currText },
} = props
let messageTextStyle
if (currText && emojiUtils.isPureEmojiString(currText)) {
messageTextStyle = {
fontSize: 28,
lineHeight: Platform.OS === 'android' ? 34 : 30,
}
}
return (<SlackMessage {...props} messageTextStyle={messageTextStyle} />)
}
dismiss = () =>
Keyboard.dismiss();
updateEmojiCount(number) {
switch (number) {
case 1:
this.setState({ reactedMessage: 0 });
break;
case 2:
this.setState({ reactedMessage: 1 });
break;
case 3:
this.setState({ reactedMessage: 2 });
break;
case 4:
this.setState({ reactedMessage: 3 });
break;
case 5:
this.setState({ reactedMessage: 4 });
break;
default:
this.forceUpdate();
}
this.setState({ reacted: true });
this.setState({ toggle: false })
}
beerEmoji() {
return (
<View>
<TouchableOpacity style={styles.emojiContainer}
onPress={() => this.updateEmojiCount(1)}>
<Image style={styles.emoji} source={require("../assets/emojis/beer.gif")} />
</TouchableOpacity>
</View>
)
}
partyEmoji() {
return (
<View>
<TouchableOpacity style={styles.emojiContainer}
onPress={() => this.updateEmojiCount(2)}>
<Image style={styles.emoji} source={require("../assets/emojis/party.gif")} />
</TouchableOpacity>
</View>
)
}
laughingEmoji() {
return (
<View>
<TouchableOpacity onPress={() => this.updateEmojiCount(3)} style={styles.emojiContainer}>
<Image style={[styles.emoji, styles.emojiResize]} source={require("../assets/emojis/laughing-emoji.gif")} />
</TouchableOpacity>
</View>
)
}
happyEmoji() {
return (
<View>
<TouchableOpacity onPress={() => this.updateEmojiCount(4)} style={styles.emojiContainer}>
<Image style={[styles.emoji, styles.emojiResize]} source={require("../assets/emojis/happy.gif")} />
</TouchableOpacity>
</View>
)
}
cryingEmoji() {
return (
<View>
<TouchableOpacity onPress={() => this.updateEmojiCount(5)} style={styles.emojiContainer}>
<Image style={[styles.emoji, styles.emojiResize]} source={require("../assets/emojis/crying.gif")} />
</TouchableOpacity>
</View>
)
}
displayEmojis() {
if (this.state.toggle) {
return (
<View
style={{
flexDirection: 'row',
right: '35%',
backgroundColor: 'white',
zIndex: 3,
overlayColor: 'white',
borderRadius: 30,
paddingHorizontal: '10%',
bottom: '2%'
}}>
{this.beerEmoji()}
{this.partyEmoji()}
{this.laughingEmoji()}
{this.happyEmoji()}
{this.cryingEmoji()}
</View>
)
}
}
toggleEmojis = (context, message) => {
let temp = this.state.messages.filter(temp => message._id == temp._id);
let id = temp[0]._id;
this.setState({ id: temp[0]._id })
if (this.state.toggle) { this.setState({ toggle: false }) }
else { this.setState({ toggle: true }) }
}
render() {
return (
<View style={{ flex: 1 }}>
<View
style={{ paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : getStatusBarHeight() }}>
<View style={{ backgroundColor: '#2c3e50', paddingVertical: '4%' }}>
<TouchableOpacity style={{ left: "89%", top: '0%' }} onPress={() => this.props.navigation.goBack()}>
<Text style={{ color: 'white' }}>Done</Text>
</TouchableOpacity>
</View>
</View>
<GiftedChat
keyboardShouldPersistTaps={'handled'}
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
placeholder={"Post something..."}
isKeyboardInternallyHandled={false}
multiline={true}
extraData={this.state}
alwaysShowSend={true}
onLongPress={this.toggleEmojis}
user={{ _id: 1 }}
renderCustomView={this.displayEmojis}
renderMessage={this.renderMessage} />
<KeyboardSpacer />
</View>
)
}
}
const styles = StyleSheet.create({
emojiContainer: {
width: 55,
height: 55,
paddingHorizontal: '13%',
right: '15%'
},
emoji: {
width: 55,
height: 55,
borderRadius: 20,
},
emojiResize: {
transform: [{ scale: 0.75 }],
},
emojiReacted: {
transform: [{ scale: 0.4 }],
},
})
//SlackMessage
import PropTypes from 'prop-types';
import React from 'react';
import {
View,
ViewPropTypes,
StyleSheet,
Image
} from 'react-native';
import { Avatar, Day, utils } from 'react-native-gifted-chat';
import Bubble from './SlackBubble';
const { isSameUser, isSameDay } = utils;
export default class Message extends React.Component {
state = {
images: [
require("../assets/emojis/beer_photo.png"),
require("../assets/emojis/party_photo.png"),
require("../assets/emojis/laughing-emoji_photo.png"),
require("../assets/emojis/happy_photo.png"),
require("../assets/emojis/crying_photo.png"),
]
}
getInnerComponentProps() {
const { containerStyle, ...props } = this.props;
return {
...props,
position: 'left',
isSameUser,
isSameDay,
};
}
renderDay() {
if (this.props.currentMessage.createdAt) {
const dayProps = this.getInnerComponentProps();
if (this.props.renderDay) {
return this.props.renderDay(dayProps);
}
return <Day {...dayProps} />;
}
return null;
}
renderBubble() {
const bubbleProps = this.getInnerComponentProps();
if (this.props.renderBubble) {
return this.props.renderBubble(bubbleProps);
}
return <Bubble {...bubbleProps} />;
}
renderAvatar() {
let extraStyle;
if (
isSameUser(this.props.currentMessage, this.props.previousMessage)
&& isSameDay(this.props.currentMessage, this.props.previousMessage)
) {
extraStyle = { height: 0 };
}
const avatarProps = this.getInnerComponentProps();
return (
<Avatar
{...avatarProps}
imageStyle={{ left: [styles.slackAvatar, avatarProps.imageStyle, extraStyle] }}
/>
);
}
render() {
const marginBottom = isSameUser(this.props.currentMessage, this.props.nextMessage) ? 2 : 10;
const { images } = this.state
const index = (this.props.extraData.reactedMessage);
return (
<View>
{this.renderDay()}
<View
style={[
styles.container,
{ marginBottom },
this.props.containerStyle,
]}>
{this.renderAvatar()}
{this.renderBubble()}
{<Image source={images[index]} style={{ width: 20, height: 20, right: '8%' }} />}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'flex-start',
marginLeft: 8,
marginRight: 8,
backgroundColor: 'white',
borderWidth: 2,
borderColor: '#BEBEBE',
paddingBottom: '3%'
},
slackAvatar: {
height: 40,
width: 40,
borderRadius: 3,
left: '10%',
bottom: '12%'
},
});
Message.defaultProps = {
renderAvatar: undefined,
renderBubble: null,
renderDay: null,
currentMessage: {},
nextMessage: {},
previousMessage: {},
user: {},
containerStyle: {},
};
Message.propTypes = {
renderAvatar: PropTypes.func,
renderBubble: PropTypes.func,
renderDay: PropTypes.func,
currentMessage: PropTypes.object,
nextMessage: PropTypes.object,
previousMessage: PropTypes.object,
user: PropTypes.object,
containerStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
};
//Bubble
import PropTypes from 'prop-types';
import React from 'react';
import {
Text,
Clipboard,
StyleSheet,
TouchableOpacity,
View,
ViewPropTypes,
Platform,
} from 'react-native';
import { MessageText, MessageImage, Time, utils } from 'react-native-gifted-chat';
const { isSameUser, isSameDay } = utils;
export default class Bubble extends React.Component {
constructor(props) {
super(props);
this.onLongPress = this.onLongPress.bind(this);
}
onLongPress() {
if (this.props.onLongPress) {
this.props.onLongPress(this.context, this.props.currentMessage);
} else {
if (this.props.currentMessage.text) {
const options = [
'Copy Text',
];
const cancelButtonIndex = options.length - 1;
this.context.actionSheet().showActionSheetWithOptions({
options,
cancelButtonIndex,
},
(buttonIndex) => {
switch (buttonIndex) {
case 0:
Clipboard.setString(this.props.currentMessage.text);
break;
}
});
}
}
}
renderMessageText() {
if (this.props.currentMessage.text) {
const { containerStyle, wrapperStyle, messageTextStyle, ...messageTextProps } = this.props;
if (this.props.renderMessageText) {
return this.props.renderMessageText(messageTextProps);
}
return (
<MessageText
{...messageTextProps}
textStyle={{
left: [styles.standardFont, styles.slackMessageText, messageTextProps.textStyle, messageTextStyle],
}}
/>
);
}
return null;
}
renderMessageImage() {
if (this.props.currentMessage.image) {
const { containerStyle, wrapperStyle, ...messageImageProps } = this.props;
if (this.props.renderMessageImage) {
return this.props.renderMessageImage(messageImageProps);
}
return <MessageImage {...messageImageProps} imageStyle={[styles.slackImage, messageImageProps.imageStyle]} />;
}
return null;
}
renderTicks() {
const { currentMessage } = this.props;
if (this.props.renderTicks) {
return this.props.renderTicks(currentMessage);
}
if (currentMessage.user._id !== this.props.user._id) {
return null;
}
if (currentMessage.sent || currentMessage.received) {
return (
<View style={[styles.headerItem, styles.tickView]}>
{currentMessage.sent && <Text style={[styles.standardFont, styles.tick, this.props.tickStyle]}>✓</Text>}
{currentMessage.received && <Text style={[styles.standardFont, styles.tick, this.props.tickStyle]}>✓</Text>}
</View>
);
}
return null;
}
renderUsername() {
const username = this.props.currentMessage.user.name;
if (username) {
const { containerStyle, wrapperStyle, ...usernameProps } = this.props;
if (this.props.renderUsername) {
return this.props.renderUsername(usernameProps);
}
return (
<Text style={[styles.standardFont, styles.headerItem, styles.username, this.props.usernameStyle]}>
{username}
</Text>
);
}
return null;
}
renderTime() {
if (this.props.currentMessage.createdAt) {
const { containerStyle, wrapperStyle, ...timeProps } = this.props;
if (this.props.renderTime) {
return this.props.renderTime(timeProps);
}
return (
<Time
{...timeProps}
containerStyle={{ left: [styles.timeContainer] }}
textStyle={{ left: [styles.standardFont, styles.headerItem, styles.time, timeProps.textStyle] }}
/>
);
}
return null;
}
renderCustomView() {
if (this.props.renderCustomView) {
return this.props.renderCustomView(this.props);
}
return null;
}
render() {
const isSameThread = isSameUser(this.props.currentMessage, this.props.previousMessage)
&& isSameDay(this.props.currentMessage, this.props.previousMessage);
const messageHeader = isSameThread ? null : (
<View style={styles.headerView}>
{this.renderUsername()}
{this.renderTime()}
{this.renderTicks()}
</View>
);
return (
<View style={[styles.container, this.props.containerStyle]}>
<TouchableOpacity
onLongPress={this.onLongPress}
accessibilityTraits="text"
{...this.props.touchableProps}
>
<View
style={[
styles.wrapper,
this.props.wrapperStyle,
]}
>
<View>
{this.renderCustomView()}
{messageHeader}
{this.renderMessageImage()}
{this.renderMessageText()}
</View>
</View>
</TouchableOpacity>
</View>
);
}
}
// Note: Everything is forced to be "left" positioned with this component.
// The "right" position is only used in the default Bubble.
const styles = StyleSheet.create({
standardFont: {
fontSize: 15,
},
slackMessageText: {
marginLeft: 0,
marginRight: 0,
},
container: {
flex: 1,
alignItems: 'flex-start',
},
wrapper: {
marginRight: 60,
minHeight: 20,
justifyContent: 'flex-end',
},
username: {
fontWeight: 'bold',
},
time: {
textAlign: 'left',
fontSize: 12,
},
timeContainer: {
marginLeft: 0,
marginRight: 0,
marginBottom: 0,
},
headerItem: {
marginRight: 10,
},
headerView: {
// Try to align it better with the avatar on Android.
marginTop: Platform.OS === 'android' ? -2 : 0,
flexDirection: 'row',
alignItems: 'baseline',
},
/* eslint-disable react-native/no-color-literals */
tick: {
backgroundColor: 'transparent',
color: 'white',
},
/* eslint-enable react-native/no-color-literals */
tickView: {
flexDirection: 'row',
},
slackImage: {
borderRadius: 3,
marginLeft: 0,
marginRight: 0,
},
});
Bubble.contextTypes = {
actionSheet: PropTypes.func,
};
Bubble.defaultProps = {
touchableProps: {},
onLongPress: null,
renderMessageImage: null,
renderMessageText: null,
renderCustomView: null,
renderTime: null,
currentMessage: {
text: null,
createdAt: null,
image: null,
},
nextMessage: {},
previousMessage: {},
containerStyle: {},
wrapperStyle: {},
tickStyle: {},
containerToNextStyle: {},
containerToPreviousStyle: {},
};
Bubble.propTypes = {
touchableProps: PropTypes.object,
onLongPress: PropTypes.func,
renderMessageImage: PropTypes.func,
renderMessageText: PropTypes.func,
renderCustomView: PropTypes.func,
renderUsername: PropTypes.func,
renderTime: PropTypes.func,
renderTicks: PropTypes.func,
currentMessage: PropTypes.object,
nextMessage: PropTypes.object,
previousMessage: PropTypes.object,
user: PropTypes.object,
containerStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
wrapperStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
messageTextStyle: Text.propTypes.style,
usernameStyle: Text.propTypes.style,
tickStyle: Text.propTypes.style,
containerToNextStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
containerToPreviousStyle: PropTypes.shape({
left: ViewPropTypes.style,
right: ViewPropTypes.style,
}),
};