From fadaee410ad8f2da4d2bb8ed9955cac9bcceef61 Mon Sep 17 00:00:00 2001 From: hippoz Date: Sun, 3 Oct 2021 01:14:10 +0300 Subject: [PATCH] feat: add message history --- bfrontend/package-lock.json | 33 +++++++++++ bfrontend/package.json | 1 + .../src/API/Gateway/GatewayConnection.js | 2 +- .../API/Gateway/globalGatewayConnection.js | 2 + .../Components/Channels/ChannelMessageView.js | 55 ++++++++++++++----- .../src/Components/Channels/ChannelView.js | 2 +- bfrontend/src/Global/store.js | 15 ++++- .../src/Styles/Components/ProfileLink.scss | 2 +- 8 files changed, 95 insertions(+), 17 deletions(-) diff --git a/bfrontend/package-lock.json b/bfrontend/package-lock.json index 62bc19e..b4fbe6e 100644 --- a/bfrontend/package-lock.json +++ b/bfrontend/package-lock.json @@ -12,6 +12,7 @@ "react": "^17.0.2", "react-content-loader": "^6.0.3", "react-dom": "^17.0.2", + "react-infinite-scroll-component": "^6.1.0", "react-media-hook": "^0.4.9", "react-redux": "^7.2.5", "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", "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": { "version": "16.13.1", "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", "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": { "version": "2.0.5", "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", "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": { "version": "16.13.1", "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", "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": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", diff --git a/bfrontend/package.json b/bfrontend/package.json index 0b599fb..cf819d0 100644 --- a/bfrontend/package.json +++ b/bfrontend/package.json @@ -7,6 +7,7 @@ "react": "^17.0.2", "react-content-loader": "^6.0.3", "react-dom": "^17.0.2", + "react-infinite-scroll-component": "^6.1.0", "react-media-hook": "^0.4.9", "react-redux": "^7.2.5", "react-router-dom": "^5.3.0", diff --git a/bfrontend/src/API/Gateway/GatewayConnection.js b/bfrontend/src/API/Gateway/GatewayConnection.js index 81ac6a1..1f6859b 100644 --- a/bfrontend/src/API/Gateway/GatewayConnection.js +++ b/bfrontend/src/API/Gateway/GatewayConnection.js @@ -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 (this.token) token = this.token; diff --git a/bfrontend/src/API/Gateway/globalGatewayConnection.js b/bfrontend/src/API/Gateway/globalGatewayConnection.js index 2d42739..cfa57a0 100644 --- a/bfrontend/src/API/Gateway/globalGatewayConnection.js +++ b/bfrontend/src/API/Gateway/globalGatewayConnection.js @@ -86,4 +86,6 @@ globalGatewayConnection.onclose = function(code) { }, 5000); }; +window.___gateway = globalGatewayConnection; + export default globalGatewayConnection; diff --git a/bfrontend/src/Components/Channels/ChannelMessageView.js b/bfrontend/src/Components/Channels/ChannelMessageView.js index 2d3383a..d1faaf4 100644 --- a/bfrontend/src/Components/Channels/ChannelMessageView.js +++ b/bfrontend/src/Components/Channels/ChannelMessageView.js @@ -1,23 +1,52 @@ import Message from "../Messages/Message"; -import { useRef, useEffect } from 'react'; -import { CommentDiscussionIcon } from "@primer/octicons-react"; +import { useRef, useEffect, useState } from '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(); + 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(() => { invisibleBottomMessageRef.current.scrollIntoView(true); }, [messages]); - let messagesView = messages.map((message) => ()); - if (messagesView === undefined || messagesView.length <= 0) - messagesView = (
- - No messages yet... -
); - - return
- { messagesView } + return
+ {messages.map(message => )}
; -} \ No newline at end of file +} diff --git a/bfrontend/src/Components/Channels/ChannelView.js b/bfrontend/src/Components/Channels/ChannelView.js index 34d65d1..1f31670 100644 --- a/bfrontend/src/Components/Channels/ChannelView.js +++ b/bfrontend/src/Components/Channels/ChannelView.js @@ -41,7 +41,7 @@ const ChannelView = ({ messages, channel, channelPresenceClientList }) => {
- +
setTextInput(target.value) }>
diff --git a/bfrontend/src/Global/store.js b/bfrontend/src/Global/store.js index 0f33f6b..432e415 100644 --- a/bfrontend/src/Global/store.js +++ b/bfrontend/src/Global/store.js @@ -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': { return { ...state, @@ -97,4 +110,4 @@ const reducer = (state = intitialState, payload) => { const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); -export default store; \ No newline at end of file +export default store; diff --git a/bfrontend/src/Styles/Components/ProfileLink.scss b/bfrontend/src/Styles/Components/ProfileLink.scss index e80b46f..1bcda17 100644 --- a/bfrontend/src/Styles/Components/ProfileLink.scss +++ b/bfrontend/src/Styles/Components/ProfileLink.scss @@ -69,7 +69,7 @@ } .profile-username { - font-weight: 500; + font-weight: 600; font-size: 1rem; line-height: 1.256rem; }