improvement: optimize ChannelMessageView and prevent sending a request for initial messages multiple times (has issues; see TODO)
This commit is contained in:
parent
3664b4e57b
commit
0090f5dc90
3 changed files with 77 additions and 34 deletions
|
@ -13,7 +13,8 @@ const intitialState = {
|
||||||
glyph: "",
|
glyph: "",
|
||||||
title: "",
|
title: "",
|
||||||
content: ""
|
content: ""
|
||||||
}
|
},
|
||||||
|
messagesLoadedIn: []
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducer = (state = intitialState, payload) => {
|
const reducer = (state = intitialState, payload) => {
|
||||||
|
@ -74,6 +75,16 @@ const reducer = (state = intitialState, payload) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'channels/firstmessageload': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
messagesLoadedIn: [
|
||||||
|
...state.messagesLoadedIn,
|
||||||
|
payload.channelId
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'channels/updatepresence': {
|
case 'channels/updatepresence': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -1,52 +1,83 @@
|
||||||
import { useRef, useEffect, useState } from 'react';
|
import { PureComponent, createRef } from 'react';
|
||||||
import { useDispatch } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
import { authenticated } from "../../api/request";
|
import { authenticated } from "../../api/request";
|
||||||
|
import { getJsonValue } from '../../common/environmentmanager';
|
||||||
import Message from "../Message";
|
import Message from "../Message";
|
||||||
|
|
||||||
export default function ChannelMessageView({ messages, channelId }) {
|
class ChannelMessageView extends PureComponent {
|
||||||
const invisibleBottomMessageRef = useRef();
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
isLoading: false
|
||||||
|
};
|
||||||
|
this.invisibleBottomMessageRef = createRef();
|
||||||
|
this.scroller = createRef();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
this.onScroll = this.onScroll.bind(this);
|
||||||
const dispatch = useDispatch();
|
}
|
||||||
const scroller = useRef();
|
|
||||||
|
|
||||||
const loadOlderMessages = () => {
|
loadOlderMessages() {
|
||||||
if (isLoading) return;
|
if (this.state.isLoading) return;
|
||||||
if (!channelId) return;
|
if (!getJsonValue("loadMessages")) return; // parse as json to get boolean
|
||||||
setIsLoading(true);
|
if (!this.props.channelId) return;
|
||||||
|
this.setState({ isLoading: true });
|
||||||
|
|
||||||
const request = messages[0] ? `/api/v1/content/channel/${channelId}/messages?before=${messages[0]._id}` : `/api/v1/content/channel/${channelId}/messages`;
|
const request = this.props.messages[0] ? `/api/v1/content/channel/${this.props.channelId}/messages?before=${this.props.messages[0]._id}` : `/api/v1/content/channel/${this.props.channelId}/messages`;
|
||||||
|
|
||||||
authenticated(request)
|
authenticated(request)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.json.channelMessages)
|
if (res.json.channelMessages)
|
||||||
dispatch({
|
this.props.dispatch({
|
||||||
type: "messagestore/addmessagesback",
|
type: "messagestore/addmessagesback",
|
||||||
messages: res.json.channelMessages.reverse(),
|
messages: res.json.channelMessages.reverse(),
|
||||||
channelId
|
channelId: this.props.channelId
|
||||||
})
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsLoading(false);
|
this.setState({ isLoading: false });
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
const onScroll = () => {
|
firstTimeMessageLoad() {
|
||||||
if (scroller.current.scrollTop === 0) {
|
if (!this.props.channelId) return false;
|
||||||
loadOlderMessages();
|
if (this.props.messagesLoadedIn.includes(this.props.channelId)) return false;
|
||||||
|
this.props.dispatch({
|
||||||
|
type: "channels/firstmessageload",
|
||||||
|
channelId: this.props.channelId
|
||||||
|
});
|
||||||
|
this.loadOlderMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
onScroll() {
|
||||||
|
// TODO: this triggers when switching between channels so the firstmessageload check does not take effect
|
||||||
|
if (this.scroller.current.scrollTop === 0)
|
||||||
|
this.loadOlderMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.firstTimeMessageLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.messages !== this.props.messages) {
|
||||||
|
this.invisibleBottomMessageRef.current.scrollIntoView(true);
|
||||||
}
|
}
|
||||||
};
|
if (prevProps.channelId !== this.props.channelId) {
|
||||||
|
this.firstTimeMessageLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
render() {
|
||||||
useEffect(loadOlderMessages, [channelId, dispatch]);
|
return <div className="message-list" id="message-list" ref={ this.scroller } onScroll={ this.onScroll }>
|
||||||
|
{this.props.messages.map(message => <Message message={message} key={message._id} />)}
|
||||||
useEffect(() => {
|
<div className="messages-scroll-div" ref={ this.invisibleBottomMessageRef }></div>
|
||||||
invisibleBottomMessageRef.current.scrollIntoView(true);
|
</div>;
|
||||||
}, [messages]);
|
}
|
||||||
|
|
||||||
return <div className="message-list" id="message-list" ref={ scroller } onScroll={ onScroll }>
|
|
||||||
{messages.map(message => <Message message={message} key={message._id} />)}
|
|
||||||
<div className="messages-scroll-div" ref={ invisibleBottomMessageRef }></div>
|
|
||||||
</div>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default connect((state) => {
|
||||||
|
return {
|
||||||
|
messagesLoadedIn: state.messagesLoadedIn
|
||||||
|
};
|
||||||
|
}, null)(ChannelMessageView);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const config = {
|
const config = {
|
||||||
apiUrl: "http://localhost:3000",
|
apiUrl: "http://localhost:3000",
|
||||||
gatewayUrl: "ws://localhost:3005/gateway",
|
gatewayUrl: "ws://localhost:3005/gateway",
|
||||||
gatewayConnectionAttributes: ["PRESENCE_UPDATES"]
|
gatewayConnectionAttributes: ["PRESENCE_UPDATES"],
|
||||||
|
loadMessages: true
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
Loading…
Reference in a new issue