sforkowany z mirror/soapbox
Chats: fix pagination bugs, use flex column-reverse
rodzic
8e6a662fbb
commit
c595e393da
|
@ -10,6 +10,8 @@ import emojify from 'soapbox/features/emoji/emoji';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { escape, throttle } from 'lodash';
|
import { escape, throttle } from 'lodash';
|
||||||
|
|
||||||
|
const scrollBottom = (elem) => elem.scrollHeight - elem.offsetHeight - elem.scrollTop;
|
||||||
|
|
||||||
const makeEmojiMap = record => record.get('emojis', ImmutableList()).reduce((map, emoji) => {
|
const makeEmojiMap = record => record.get('emojis', ImmutableList()).reduce((map, emoji) => {
|
||||||
return map.set(`:${emoji.get('shortcode')}:`, emoji);
|
return map.set(`:${emoji.get('shortcode')}:`, emoji);
|
||||||
}, ImmutableMap());
|
}, ImmutableMap());
|
||||||
|
@ -19,7 +21,7 @@ const mapStateToProps = (state, { chatMessageIds }) => ({
|
||||||
chatMessages: chatMessageIds.reduce((acc, curr) => {
|
chatMessages: chatMessageIds.reduce((acc, curr) => {
|
||||||
const chatMessage = state.getIn(['chat_messages', curr]);
|
const chatMessage = state.getIn(['chat_messages', curr]);
|
||||||
return chatMessage ? acc.push(chatMessage) : acc;
|
return chatMessage ? acc.push(chatMessage) : acc;
|
||||||
}, ImmutableList()).sort(),
|
}, ImmutableList()).sort().reverse(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -39,6 +41,10 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
chatMessages: ImmutableList(),
|
chatMessages: ImmutableList(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
isLoading: false,
|
||||||
|
}
|
||||||
|
|
||||||
scrollToBottom = () => {
|
scrollToBottom = () => {
|
||||||
if (!this.messagesEnd) return;
|
if (!this.messagesEnd) return;
|
||||||
this.messagesEnd.scrollIntoView();
|
this.messagesEnd.scrollIntoView();
|
||||||
|
@ -46,7 +52,6 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
|
|
||||||
setMessageEndRef = (el) => {
|
setMessageEndRef = (el) => {
|
||||||
this.messagesEnd = el;
|
this.messagesEnd = el;
|
||||||
this.scrollToBottom();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
getFormattedTimestamp = (chatMessage) => {
|
getFormattedTimestamp = (chatMessage) => {
|
||||||
|
@ -75,11 +80,19 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.node.addEventListener('scroll', this.handleScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (prevProps.chatMessages !== this.props.chatMessages)
|
const oldCount = prevProps.chatMessages.count();
|
||||||
this.scrollToBottom();
|
const newCount = this.props.chatMessages.count();
|
||||||
|
const isNearBottom = scrollBottom(this.node) < 150;
|
||||||
|
const historyAdded = prevProps.chatMessages.getIn([-1, 'id']) !== this.props.chatMessages.getIn([-1, 'id']);
|
||||||
|
|
||||||
|
if (oldCount !== newCount) {
|
||||||
|
if (isNearBottom) this.scrollToBottom();
|
||||||
|
if (historyAdded) this.setState({ isLoading: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -87,13 +100,14 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoadMore = () => {
|
handleLoadMore = () => {
|
||||||
const { dispatch, chatId, chatMessageIds } = this.props;
|
const { dispatch, chatId, chatMessages } = this.props;
|
||||||
const maxId = chatMessageIds.last();
|
const maxId = chatMessages.getIn([-1, 'id']);
|
||||||
dispatch(fetchChatMessages(chatId, maxId));
|
dispatch(fetchChatMessages(chatId, maxId));
|
||||||
|
this.setState({ isLoading: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleScroll = throttle(() => {
|
handleScroll = throttle(() => {
|
||||||
if (this.node.scrollTop < 100) this.handleLoadMore();
|
if (this.node.scrollTop < 150 && !this.state.isLoading) this.handleLoadMore();
|
||||||
}, 150, {
|
}, 150, {
|
||||||
trailing: true,
|
trailing: true,
|
||||||
});
|
});
|
||||||
|
@ -112,7 +126,6 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
|
|
||||||
setRef = (c) => {
|
setRef = (c) => {
|
||||||
this.node = c;
|
this.node = c;
|
||||||
this.node.addEventListener('scroll', this.handleScroll);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -120,6 +133,7 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='chat-messages' ref={this.setRef}>
|
<div className='chat-messages' ref={this.setRef}>
|
||||||
|
<div style={{ float: 'left', clear: 'both' }} ref={this.setMessageEndRef} />
|
||||||
{chatMessages.map(chatMessage => (
|
{chatMessages.map(chatMessage => (
|
||||||
<div
|
<div
|
||||||
className={classNames('chat-message', {
|
className={classNames('chat-message', {
|
||||||
|
@ -136,7 +150,6 @@ class ChatMessageList extends ImmutablePureComponent {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div style={{ float: 'left', clear: 'both' }} ref={this.setMessageEndRef} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,12 +99,18 @@
|
||||||
.chat-messages {
|
.chat-messages {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message {
|
.chat-message {
|
||||||
margin: 14px 10px;
|
padding: 7px 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
&__bubble {
|
&__bubble {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
padding: 4px 10px;
|
padding: 4px 10px;
|
||||||
|
|
Ładowanie…
Reference in New Issue