Chats: add the building blocks for pagination

merge-requests/214/head
Alex Gleason 4 years ago
parent 48083e7f86
commit 0e7132d25e
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7

@ -34,13 +34,13 @@ export function fetchChats() {
};
}
export function fetchChatMessages(chatId) {
export function fetchChatMessages(chatId, maxId = null) {
return (dispatch, getState) => {
dispatch({ type: CHAT_MESSAGES_FETCH_REQUEST, chatId });
return api(getState).get(`/api/v1/pleroma/chats/${chatId}/messages`).then(({ data }) => {
dispatch({ type: CHAT_MESSAGES_FETCH_SUCCESS, chatId, chatMessages: data });
dispatch({ type: CHAT_MESSAGES_FETCH_REQUEST, chatId, maxId });
return api(getState).get(`/api/v1/pleroma/chats/${chatId}/messages`, { params: { max_id: maxId } }).then(({ data }) => {
dispatch({ type: CHAT_MESSAGES_FETCH_SUCCESS, chatId, maxId, chatMessages: data });
}).catch(error => {
dispatch({ type: CHAT_MESSAGES_FETCH_FAIL, chatId, error });
dispatch({ type: CHAT_MESSAGES_FETCH_FAIL, chatId, maxId, error });
});
};
}

@ -98,12 +98,12 @@ class ChatBox extends ImmutablePureComponent {
}
render() {
const { chatMessageIds, intl } = this.props;
const { chatMessageIds, chatId, intl } = this.props;
if (!chatMessageIds) return null;
return (
<div className='chat-box' onMouseOver={this.handleHover}>
<ChatMessageList chatMessageIds={chatMessageIds} />
<ChatMessageList chatMessageIds={chatMessageIds} chatId={chatId} />
<div className='chat-box__actions simple_form'>
<textarea
rows={1}

@ -5,9 +5,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { fetchChatMessages } from 'soapbox/actions/chats';
import emojify from 'soapbox/features/emoji/emoji';
import classNames from 'classnames';
import { escape } from 'lodash';
import { escape, throttle } from 'lodash';
const makeEmojiMap = record => record.get('emojis', ImmutableList()).reduce((map, emoji) => {
return map.set(`:${emoji.get('shortcode')}:`, emoji);
@ -28,6 +29,7 @@ class ChatMessageList extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
chatId: PropTypes.string,
chatMessages: ImmutablePropTypes.list,
chatMessageIds: ImmutablePropTypes.orderedSet,
me: PropTypes.node,
@ -61,7 +63,7 @@ class ChatMessageList extends ImmutablePureComponent {
);
};
setRef = (c) => {
setBubbleRef = (c) => {
if (!c) return;
const links = c.querySelectorAll('a[rel="ugc"]');
@ -72,11 +74,30 @@ class ChatMessageList extends ImmutablePureComponent {
});
}
componentDidMount() {
}
componentDidUpdate(prevProps) {
if (prevProps.chatMessages !== this.props.chatMessages)
this.scrollToBottom();
}
componentWillUnmount() {
this.node.removeEventListener('scroll', this.handleScroll);
}
handleLoadMore = () => {
const { dispatch, chatId, chatMessageIds } = this.props;
const maxId = chatMessageIds.last();
dispatch(fetchChatMessages(chatId, maxId));
}
handleScroll = throttle(() => {
if (this.node.scrollTop < 100) this.handleLoadMore();
}, 150, {
trailing: true,
});
parsePendingContent = content => {
return escape(content).replace(/(?:\r\n|\r|\n)/g, '<br>');
}
@ -89,11 +110,16 @@ class ChatMessageList extends ImmutablePureComponent {
return emojify(formatted, emojiMap.toJS());
}
setRef = (c) => {
this.node = c;
this.node.addEventListener('scroll', this.handleScroll);
}
render() {
const { chatMessages, me } = this.props;
return (
<div className='chat-messages'>
<div className='chat-messages' ref={this.setRef}>
{chatMessages.map(chatMessage => (
<div
className={classNames('chat-message', {
@ -106,7 +132,7 @@ class ChatMessageList extends ImmutablePureComponent {
title={this.getFormattedTimestamp(chatMessage)}
className='chat-message__bubble'
dangerouslySetInnerHTML={{ __html: this.parseContent(chatMessage) }}
ref={this.setRef}
ref={this.setBubbleRef}
/>
</div>
))}

Loading…
Cancel
Save