Chats: improve performance

merge-requests/568/head
Alex Gleason 2021-07-01 18:01:33 -05:00
rodzic 74e6d8ce81
commit 799f19bbc4
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
4 zmienionych plików z 72 dodań i 51 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
import React from 'react';
import { connect } from 'react-redux';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import Avatar from '../../../components/avatar';
@ -6,11 +7,29 @@ import DisplayName from '../../../components/display_name';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { shortNumberFormat } from 'soapbox/utils/numbers';
import emojify from 'soapbox/features/emoji/emoji';
import { makeGetChat } from 'soapbox/selectors';
export default class Chat extends ImmutablePureComponent {
const makeMapStateToProps = () => {
const getChat = makeGetChat();
const mapStateToProps = (state, { chatId }) => {
const chat = state.getIn(['chats', chatId]);
return {
chat: chat ? getChat(state, chat.toJS()) : undefined,
};
};
return mapStateToProps;
};
export default @connect(makeMapStateToProps)
class Chat extends ImmutablePureComponent {
static propTypes = {
chat: ImmutablePropTypes.map.isRequired,
chatId: PropTypes.string.isRequired,
chat: ImmutablePropTypes.map,
onClick: PropTypes.func,
};

Wyświetl plik

@ -1,10 +1,10 @@
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Chat from './chat';
import { makeGetChat } from 'soapbox/selectors';
const chatDateComparator = (chatA, chatB) => {
// Sort most recently updated chats at the top
@ -18,15 +18,13 @@ const chatDateComparator = (chatA, chatB) => {
};
const mapStateToProps = state => {
const getChat = makeGetChat();
const chats = state.get('chats')
.map(chat => getChat(state, chat.toJS()))
const chatIds = state.get('chats')
.toList()
.sort(chatDateComparator);
.sort(chatDateComparator)
.map(chat => chat.get('id'));
return {
chats,
chatIds,
};
};
@ -37,23 +35,24 @@ class ChatList extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
chatIds: ImmutablePropTypes.list,
onClickChat: PropTypes.func,
emptyMessage: PropTypes.node,
};
render() {
const { chats, emptyMessage } = this.props;
const { chatIds, emptyMessage } = this.props;
return (
<div className='chat-list'>
<div className='chat-list__content'>
{chats.count() === 0 &&
{chatIds.count() === 0 &&
<div className='empty-column-indicator'>{emptyMessage}</div>
}
{chats.map(chat => (
<div key={chat.get('id')} className='chat-list-item'>
{chatIds.map(chatId => (
<div key={chatId} className='chat-list-item'>
<Chat
chat={chat}
chatId={chatId}
onClick={this.props.onClickChat}
/>
</div>

Wyświetl plik

@ -6,30 +6,17 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { getSettings } from 'soapbox/actions/settings';
import ChatList from './chat_list';
import { FormattedMessage } from 'react-intl';
import { makeGetChat } from 'soapbox/selectors';
import { openChat, toggleMainWindow } from 'soapbox/actions/chats';
import ChatWindow from './chat_window';
import { shortNumberFormat } from 'soapbox/utils/numbers';
import AudioToggle from 'soapbox/features/chats/components/audio_toggle';
import { List as ImmutableList } from 'immutable';
const addChatsToPanes = (state, panesData) => {
const getChat = makeGetChat();
const newPanes = panesData.get('panes').reduce((acc, pane) => {
const chat = getChat(state, { id: pane.get('chat_id') });
if (!chat) return acc;
return acc.push(pane.set('chat', chat));
}, ImmutableList());
return panesData.set('panes', newPanes);
};
const mapStateToProps = state => {
const panesData = getSettings(state).get('chats');
const settings = getSettings(state);
return {
panesData: addChatsToPanes(state, panesData),
panes: settings.getIn(['chats', 'panes']),
mainWindowState: settings.getIn(['chats', 'mainWindow']),
unreadCount: state.get('chats').reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0),
};
};
@ -39,7 +26,8 @@ class ChatPanes extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
panesData: ImmutablePropTypes.map,
mainWindowState: PropTypes.string,
panes: ImmutablePropTypes.list,
}
handleClickChat = (chat) => {
@ -51,12 +39,10 @@ class ChatPanes extends ImmutablePureComponent {
}
render() {
const { panesData, unreadCount } = this.props;
const panes = panesData.get('panes');
const mainWindow = panesData.get('mainWindow');
const { panes, mainWindowState, unreadCount } = this.props;
const mainWindowPane = (
<div className={`pane pane--main pane--${mainWindow}`}>
<div className={`pane pane--main pane--${mainWindowState}`}>
<div className='pane__header'>
{unreadCount > 0 && <i className='icon-with-badge__badge'>{shortNumberFormat(unreadCount)}</i>}
<button className='pane__title' onClick={this.handleMainWindowToggle}>
@ -76,9 +62,14 @@ class ChatPanes extends ImmutablePureComponent {
return (
<div className='chat-panes'>
{mainWindowPane}
{panes.map((pane, i) =>
<ChatWindow idx={i} pane={pane} key={pane.get('chat_id')} />,
)}
{panes.map((pane, i) => (
<ChatWindow
idx={i}
key={pane.get('chat_id')}
chatId={pane.get('chat_id')}
windowState={pane.get('state')}
/>
))}
</div>
);
}

Wyświetl plik

@ -16,21 +16,33 @@ import ChatBox from './chat_box';
import { shortNumberFormat } from 'soapbox/utils/numbers';
import { displayFqn } from 'soapbox/utils/state';
import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper';
import { makeGetChat } from 'soapbox/selectors';
const mapStateToProps = (state, { pane }) => ({
me: state.get('me'),
chat: state.getIn(['chats', pane.get('chat_id')]),
displayFqn: displayFqn(state),
});
const makeMapStateToProps = () => {
const getChat = makeGetChat();
export default @connect(mapStateToProps)
const mapStateToProps = (state, { chatId }) => {
const chat = state.getIn(['chats', chatId]);
return {
me: state.get('me'),
chat: chat ? getChat(state, chat.toJS()) : undefined,
displayFqn: displayFqn(state),
};
};
return mapStateToProps;
};
export default @connect(makeMapStateToProps)
@injectIntl
class ChatWindow extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
pane: ImmutablePropTypes.map.isRequired,
chatId: PropTypes.string.isRequired,
windowState: PropTypes.string.isRequired,
idx: PropTypes.number,
chat: ImmutablePropTypes.map,
me: PropTypes.node,
@ -68,17 +80,17 @@ class ChatWindow extends ImmutablePureComponent {
}
componentDidUpdate(prevProps) {
const oldState = prevProps.pane.get('state');
const newState = this.props.pane.get('state');
const oldState = prevProps.windowState;
const newState = this.props.windowState;
if (oldState !== newState && newState === 'open')
this.focusInput();
}
render() {
const { pane, idx, chat, displayFqn } = this.props;
const account = pane.getIn(['chat', 'account']);
if (!chat || !account) return null;
const { windowState, idx, chat, displayFqn } = this.props;
if (!chat) return null;
const account = chat.get('account');
const right = (285 * (idx + 1)) + 20;
const unreadCount = chat.get('unread');
@ -98,7 +110,7 @@ class ChatWindow extends ImmutablePureComponent {
);
return (
<div className={`pane pane--${pane.get('state')}`} style={{ right: `${right}px` }}>
<div className={`pane pane--${windowState}`} style={{ right: `${right}px` }}>
<div className='pane__header'>
{unreadCount > 0 ? unreadIcon : avatar }
<button className='pane__title' onClick={this.handleChatToggle(chat.get('id'))}>