Hi every one, I want to animate a progressbar for every sound message duration when gets played, I have a PLAY ICON for any sound message, when I click on play icon, sound starts as well and I update the progressbar by setState, actually the progress gets update but the problem is my progressbar doesnt re-render to get progress value for progressbar. and also the play icon does not re-render to get red color.
I got something from:
render(){
return (
<GiftedChat
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
user={{
_id: this.state.userId,
}}
renderBubble={this.renderBubble}
renderInputToolbar={this.renderInputToolbar.bind(this)}
/>
);
}
renderBubble = props => {
if (props.currentMessage.audio) {
return (
<View style={[{ width: 150, height: 70, backgroundColor: 'lightgray' }, props.position === 'left' ? { left: -41 } : {}]}>
<EIcon
name="google-play"
size={30}
color={this.state.playAudio ? "red" : "blue"}
style={{
left: 90,
position: "relative",
shadowColor: "#000",
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.5,
backgroundColor: "transparent"
}}
onPress={() => {
this.setState({
playAudio: true
});
const sound = new Sound(props.currentMessage.audio, "", error => {
if (error) {
console.log("failed to load the sound", error);
}
const duration = sound.getDuration();
const progressPhase = 1 / duration;
if (duration !== 0) {
this._interval = setInterval(() => {
this.setState({
progress: this.state.progress += progressPhase
});
if (this.state.progress >= 1) {
clearInterval(this._interval);
this.setState({
progress: 0.0,
playAudio: false
});
}
}, 1000);
}
sound.play(success => {
console.log(success, "success play");
if (!success) {
Alert.alert("There was an error playing this audio");
}
});
});
}}
/>
<Progress.Circle progress={this.state.progress} showsText size={35} />
</View>
);
} else {
return (
<Bubble
{...props}
textStyle={{
right: {
color: '#fff',
},
left: {
color: '#fff',
},
}}
wrapperStyle={{
left: {
backgroundColor: "orange",
left: -41
},
right: {
backgroundColor: 'green'
}
}}
/>
);
}
}
I want to re-render progressbar with updating state { progress: 0.0 } when I call
this.setState({
progress: this.state.progress += progressPhase
});
// this should be re-render on every update
<Progress.Circle progress={this.state.progress} showsText size={35} />
Actually I found the problem but still I dont know what is the solutions,
The problem is with react-native-gifted-chat version 0.7.2
The above code works well on react-native-gifted-chat version 0.4.3
In version 0.4.3 there when I click play icon all sound message progessbar starts progressing instead of the one I clicked. I want just the one should start progressing which I have clicked.
Sorry about that.
Maybe try to use extraData props?
Hi thank you for replying, could you please let me know how can I use extraData in react-native-gifted-chat?
best regrads
On Feb 2, 2019, at 6:20 PM, Xavier Carpentier notifications@github.com wrote:
@xcarpentier thank you, my problem has solved by adding extraData={this.state} to Giftedchat
and now please help me how can I start just one progress at a time?
Because now it gets update but by clicking one sound message just the last sound message gets update and re-rendered.
Easy way to understand what is my question play the following video and see what is my problem. https://vimeo.com/315390850
Can you share your code somewhere?
Hi @xcarpentier,
Now I solved this problem by conditional rendering Also I changed following class and I added
this line: _next.audio == current.audio ||_
export default class Message extends React.Component {
shouldComponentUpdate(nextProps) {
const next = nextProps.currentMessage;
const current = this.props.currentMessage;
const { nextMessage } = this.props;
const nextPropsMessage = nextProps.nextMessage;
return (
next.send !== current.send ||
next.received !== current.received ||
next.pending !== current.pending ||
next.createdAt !== current.createdAt ||
next.text !== current.text ||
next.image !== current.image ||
next.video !== current.video ||
next.audio == current.audio || // this line added by me
nextMessage !== nextPropsMessage
);
}
//..............
}
I add this condition and please please let me know about performance.
this tree line, I added to my code:
_this.myPro = <Progress.Circle progress={this.state.progress} showsText size={35} />;
this.setState({currentPlayedMessage: props.currentMessage._id });
{ props.currentMessage._id === this.state.currentPlayedMessage ? this.myPro : null }_
All code:
if (props.currentMessage.audio) {
this.myPro = <Progress.Circle progress={this.state.progress} showsText size={35} />; // this line added
return (
<View style={[{ width: 150, height: 70, backgroundColor: 'lightgray' }, props.position === 'left' ? { left: -41 } : {}]}>
<EIcon
name="google-play"
size={30}
color={this.state.playAudio ? "green" : "blue"}
style={{
left: 90,
position: "relative",
shadowColor: "#000",
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.5,
backgroundColor: "transparent"
}}
onPress={() => {
this.setState({
playAudio: true,
currentPlayedMessage: props.currentMessage._id // this line added
});
const sound = new Sound(props.currentMessage.audio, "", error => {
if (error) {
return;
}
const duration = sound.getDuration();
const progressPhase = 1 / duration;
if (duration !== 0) {
this._interval = setInterval(() => {
this.setState({
progress: this.state.progress += progressPhase
});
if (this.state.progress >= 1) {
clearInterval(this._interval);
this.setState({
progress: 0.0,
playAudio: false
});
}
}, 1000);
}
sound.play(success => {
console.log(success, "success play");
if (!success) {
Alert.alert("There was an error playing this audio");
}
});
});
}}
/>
{ props.currentMessage._id === this.state.currentPlayedMessage ? this.myPro : null } // this line added
</View>
);
}
Should be next.audio !== current.audio?
Because should update is audio is different.
@xcarpentier thank you to replying, I tried that, but unfortunatly it just work with last audio message has came.
my audio message is like this:
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, {
_id: data.id,
audio: data.audio,
messageType: 'audio',
createdAt: new Date(),
user: {
_id: '2'
},
renderAvatar: null
}),
}));
I mean if I put it like this:
next.audio !== current.audio
there the last audio message gets render.
but if I put like this:
next.audio == current.audio
all audio messages gets render.
Hi, I dont know this line is send or sent
next.send !== current.send ?
next.sent !== current.sent ?
You are right this is sent:
https://github.com/FaridSafi/react-native-gifted-chat/search?q=sent&unscoped_q=sent
I will change it...
I'm having the same issue with only the last message re-rendering. Using the latest commit hash as my package.
Solved this issue by forking and implementing a special shouldUpdateMessage function. This allows for special use cases around when to re-render messages.
Let me know if you'd like to me to PR this. Feel free to steal the code.
馃憤
Yes please create a PR
@mykewould
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Most helpful comment
Sorry about that.
Maybe try to use
extraDataprops?