diff --git a/app/lib/components/Chat/MessageList.jsx b/app/lib/components/Chat/MessageList.jsx
index 3f59d1a..e80e17b 100644
--- a/app/lib/components/Chat/MessageList.jsx
+++ b/app/lib/components/Chat/MessageList.jsx
@@ -1,14 +1,9 @@
import React, { Component } from 'react';
+import { compose } from 'redux';
import PropTypes from 'prop-types';
import marked from 'marked';
import { connect } from 'react-redux';
-
-const scrollToBottom = () =>
-{
- const messagesDiv = document.getElementById('messages');
-
- messagesDiv.scrollTop = messagesDiv.scrollHeight;
-};
+import scrollToBottom from './scrollToBottom';
const linkRenderer = new marked.Renderer();
@@ -22,16 +17,6 @@ linkRenderer.link = (href, title, text) =>
class MessageList extends Component
{
- componentDidMount()
- {
- scrollToBottom();
- }
-
- componentDidUpdate()
- {
- scrollToBottom();
- }
-
getTimeString(time)
{
return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`;
@@ -96,8 +81,9 @@ const mapStateToProps = (state) =>
};
};
-const MessageListContainer = connect(
- mapStateToProps
+const MessageListContainer = compose(
+ connect(mapStateToProps),
+ scrollToBottom()
)(MessageList);
export default MessageListContainer;
diff --git a/app/lib/components/Chat/scrollToBottom.jsx b/app/lib/components/Chat/scrollToBottom.jsx
new file mode 100644
index 0000000..2a107a4
--- /dev/null
+++ b/app/lib/components/Chat/scrollToBottom.jsx
@@ -0,0 +1,63 @@
+import React, { Component } from 'react';
+import { findDOMNode } from 'react-dom';
+
+/**
+ * A higher order component which scrolls the user to the bottom of the
+ * wrapped component, provided that the user already was at the bottom
+ * of the wrapped component. Useful for chats and similar use cases.
+ * @param {number} treshold The required distance from the bottom required.
+ */
+const scrollToBottom = (treshold = 0) => (WrappedComponent) =>
+{
+ return class AutoScroller extends Component
+ {
+ constructor(props)
+ {
+ super(props);
+
+ this.ref = React.createRef();
+ }
+
+ getSnapshotBeforeUpdate()
+ {
+ // Check if the user has scrolled close enough to the bottom for
+ // us to scroll to the bottom or not.
+ return this.elem.scrollHeight - this.elem.scrollTop <=
+ this.elem.clientHeight - treshold;
+ }
+
+ scrollToBottom = () =>
+ {
+ // Scroll the user to the bottom of the wrapped element.
+ this.elem.scrollTop = this.elem.scrollHeight;
+ };
+
+ componentDidMount()
+ {
+ // eslint-disable-next-line react/no-find-dom-node
+ this.elem = findDOMNode(this.ref.current);
+
+ this.scrollToBottom();
+ }
+
+ componentDidUpdate(prevProps, prevState, atBottom)
+ {
+ if (atBottom)
+ {
+ this.scrollToBottom();
+ }
+ }
+
+ render()
+ {
+ return (
+