feat: add message history
This commit is contained in:
parent
47ef5dd6fc
commit
fadaee410a
8 changed files with 95 additions and 17 deletions
33
bfrontend/package-lock.json
generated
33
bfrontend/package-lock.json
generated
|
@ -12,6 +12,7 @@
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-content-loader": "^6.0.3",
|
"react-content-loader": "^6.0.3",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-infinite-scroll-component": "^6.1.0",
|
||||||
"react-media-hook": "^0.4.9",
|
"react-media-hook": "^0.4.9",
|
||||||
"react-redux": "^7.2.5",
|
"react-redux": "^7.2.5",
|
||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
|
@ -16076,6 +16077,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
||||||
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-infinite-scroll-component": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"throttle-debounce": "^2.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
@ -18892,6 +18904,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
|
||||||
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
|
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/throttle-debounce": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/through2": {
|
"node_modules/through2": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||||
|
@ -33610,6 +33630,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
||||||
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
||||||
},
|
},
|
||||||
|
"react-infinite-scroll-component": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==",
|
||||||
|
"requires": {
|
||||||
|
"throttle-debounce": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
@ -35840,6 +35868,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
|
||||||
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
|
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
|
||||||
},
|
},
|
||||||
|
"throttle-debounce": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ=="
|
||||||
|
},
|
||||||
"through2": {
|
"through2": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-content-loader": "^6.0.3",
|
"react-content-loader": "^6.0.3",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-infinite-scroll-component": "^6.1.0",
|
||||||
"react-media-hook": "^0.4.9",
|
"react-media-hook": "^0.4.9",
|
||||||
"react-redux": "^7.2.5",
|
"react-redux": "^7.2.5",
|
||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
|
|
|
@ -60,7 +60,7 @@ class GatewayConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GatewayConnection.prototype.connect = function(token, attributes=["PRESENCE_UPDATES"]) {
|
GatewayConnection.prototype.connect = function(token, attributes=["PRESENCE_UPDATES", "SAVE_MESSAGES"]) {
|
||||||
if (token) this.token = token;
|
if (token) this.token = token;
|
||||||
if (this.token) token = this.token;
|
if (this.token) token = this.token;
|
||||||
|
|
||||||
|
|
|
@ -86,4 +86,6 @@ globalGatewayConnection.onclose = function(code) {
|
||||||
}, 5000);
|
}, 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.___gateway = globalGatewayConnection;
|
||||||
|
|
||||||
export default globalGatewayConnection;
|
export default globalGatewayConnection;
|
||||||
|
|
|
@ -1,23 +1,52 @@
|
||||||
import Message from "../Messages/Message";
|
import Message from "../Messages/Message";
|
||||||
import { useRef, useEffect } from 'react';
|
import { useRef, useEffect, useState } from 'react';
|
||||||
import { CommentDiscussionIcon } from "@primer/octicons-react";
|
import APIRequest from "../../API/APIRequest";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
export default function ChannelMessageView({messages}) {
|
export default function ChannelMessageView({messages, channelId}) {
|
||||||
const invisibleBottomMessageRef = useRef();
|
const invisibleBottomMessageRef = useRef();
|
||||||
|
|
||||||
|
console.log(messages);
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const scroller = useRef();
|
||||||
|
|
||||||
|
const loadOlderMessages = () => {
|
||||||
|
if (isLoading) return;
|
||||||
|
if (!channelId) return;
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const request = messages[0] ? `/api/v1/content/channel/${channelId}/messages?before=${messages[0]._id}` : `/api/v1/content/channel/${channelId}/messages`;
|
||||||
|
|
||||||
|
APIRequest.authenticated(request)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.json.channelMessages)
|
||||||
|
dispatch({
|
||||||
|
type: "messagestore/addmessagesback",
|
||||||
|
messages: res.json.channelMessages.reverse(),
|
||||||
|
channelId
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onScroll = () => {
|
||||||
|
if (scroller.current.scrollTop === 0) {
|
||||||
|
loadOlderMessages();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(loadOlderMessages, [channelId, dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
invisibleBottomMessageRef.current.scrollIntoView(true);
|
invisibleBottomMessageRef.current.scrollIntoView(true);
|
||||||
}, [messages]);
|
}, [messages]);
|
||||||
|
|
||||||
let messagesView = messages.map((message) => (<Message key={message._id} message={message} />));
|
return <div className="message-list" id="message-list" ref={ scroller } onScroll={ onScroll }>
|
||||||
if (messagesView === undefined || messagesView.length <= 0)
|
{messages.map(message => <Message message={message} key={message._id} />)}
|
||||||
messagesView = (<div className='no-messages-warning'>
|
|
||||||
<CommentDiscussionIcon size={64} />
|
|
||||||
<span style={{ margin: "12px" }}>No messages yet...</span>
|
|
||||||
</div>);
|
|
||||||
|
|
||||||
return <div className="message-list">
|
|
||||||
{ messagesView }
|
|
||||||
<div className="messages-scroll-div" ref={ invisibleBottomMessageRef }></div>
|
<div className="messages-scroll-div" ref={ invisibleBottomMessageRef }></div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
|
@ -41,7 +41,7 @@ const ChannelView = ({ messages, channel, channelPresenceClientList }) => {
|
||||||
|
|
||||||
<div className="row-flex hidden-overflow">
|
<div className="row-flex hidden-overflow">
|
||||||
<div className="channel-message-panel">
|
<div className="channel-message-panel">
|
||||||
<ChannelMessageView messages={messages}></ChannelMessageView>
|
<ChannelMessageView messages={messages} channelId={channel._id}></ChannelMessageView>
|
||||||
<div className="col-flex">
|
<div className="col-flex">
|
||||||
<input className="text-input message-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
|
<input className="text-input message-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -54,6 +54,19 @@ const reducer = (state = intitialState, payload) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'messagestore/addmessagesback': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
messages: {
|
||||||
|
...state.messages,
|
||||||
|
[payload.channelId]: [
|
||||||
|
...payload.messages,
|
||||||
|
...state.messages[payload.channelId] || []
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'channels/selectchannel': {
|
case 'channels/selectchannel': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-username {
|
.profile-username {
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 1.256rem;
|
line-height: 1.256rem;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue