kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Chats: improve performance
rodzic
74e6d8ce81
commit
799f19bbc4
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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'))}>
|
||||
|
|
Ładowanie…
Reference in New Issue