Chats: add unread counters to chats

loading-indicator-on-tls^2
Alex Gleason 2020-08-27 15:43:19 -05:00
rodzic 020e21adcd
commit ac028ed584
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
5 zmienionych plików z 36 dodań i 4 usunięć

Wyświetl plik

@ -20,8 +20,14 @@ const chatDateComparator = (chatA, chatB) => {
const mapStateToProps = state => { const mapStateToProps = state => {
const getChat = makeGetChat(); const getChat = makeGetChat();
const chats = state.get('chats')
.map(chat => getChat(state, chat.toJS()))
.toList()
.sort(chatDateComparator);
return { return {
chats: state.get('chats').map(chat => getChat(state, chat.toJS())).toList().sort(chatDateComparator), chats,
}; };
}; };

Wyświetl plik

@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import Avatar from '../../../components/avatar'; import Avatar from '../../../components/avatar';
import DisplayName from '../../../components/display_name'; import DisplayName from '../../../components/display_name';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { shortNumberFormat } from 'soapbox/utils/numbers';
export default class ChatListAccount extends ImmutablePureComponent { export default class ChatListAccount extends ImmutablePureComponent {
@ -20,6 +21,7 @@ export default class ChatListAccount extends ImmutablePureComponent {
const { chat } = this.props; const { chat } = this.props;
if (!chat) return null; if (!chat) return null;
const account = chat.get('account'); const account = chat.get('account');
const unreadCount = chat.get('unread');
return ( return (
<div className='account'> <div className='account'>
@ -30,6 +32,7 @@ export default class ChatListAccount extends ImmutablePureComponent {
<Avatar account={account} size={36} /> <Avatar account={account} size={36} />
</div> </div>
<DisplayName account={account} /> <DisplayName account={account} />
{unreadCount > 0 && <i className='icon-with-badge__badge'>{shortNumberFormat(unreadCount)}</i>}
</div> </div>
</div> </div>
</div> </div>

Wyświetl plik

@ -10,6 +10,7 @@ import { FormattedMessage } from 'react-intl';
import { makeGetChat } from 'soapbox/selectors'; import { makeGetChat } from 'soapbox/selectors';
import { openChat, toggleMainWindow } from 'soapbox/actions/chats'; import { openChat, toggleMainWindow } from 'soapbox/actions/chats';
import ChatWindow from './chat_window'; import ChatWindow from './chat_window';
import { shortNumberFormat } from 'soapbox/utils/numbers';
const addChatsToPanes = (state, panesData) => { const addChatsToPanes = (state, panesData) => {
const getChat = makeGetChat(); const getChat = makeGetChat();
@ -27,6 +28,7 @@ const mapStateToProps = state => {
return { return {
panesData: addChatsToPanes(state, panesData), panesData: addChatsToPanes(state, panesData),
unreadCount: state.get('chats').reduce((acc, curr) => acc + curr.get('unread'), 0),
}; };
}; };
@ -50,7 +52,7 @@ class ChatPanes extends ImmutablePureComponent {
} }
render() { render() {
const { panesData } = this.props; const { panesData, unreadCount } = this.props;
const panes = panesData.get('panes'); const panes = panesData.get('panes');
const mainWindow = panesData.get('mainWindow'); const mainWindow = panesData.get('mainWindow');
@ -60,6 +62,7 @@ class ChatPanes extends ImmutablePureComponent {
<button className='pane__title' onClick={this.handleMainWindowToggle}> <button className='pane__title' onClick={this.handleMainWindowToggle}>
<FormattedMessage id='chat_panels.main_window.title' defaultMessage='Chats' /> <FormattedMessage id='chat_panels.main_window.title' defaultMessage='Chats' />
</button> </button>
{unreadCount > 0 && <i className='icon-with-badge__badge'>{shortNumberFormat(unreadCount)}</i>}
</div> </div>
<div className='pane__content'> <div className='pane__content'>
<ChatList <ChatList

Wyświetl plik

@ -10,9 +10,11 @@ import IconButton from 'soapbox/components/icon_button';
import { closeChat, toggleChat, fetchChatMessages, sendChatMessage } from 'soapbox/actions/chats'; import { closeChat, toggleChat, fetchChatMessages, sendChatMessage } from 'soapbox/actions/chats';
import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable'; import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable';
import ChatMessageList from './chat_message_list'; import ChatMessageList from './chat_message_list';
import { shortNumberFormat } from 'soapbox/utils/numbers';
const mapStateToProps = (state, { pane }) => ({ const mapStateToProps = (state, { pane }) => ({
me: state.get('me'), me: state.get('me'),
chat: state.getIn(['chats', pane.get('chat_id')]),
chatMessageIds: state.getIn(['chat_message_lists', pane.get('chat_id')], ImmutableOrderedSet()), chatMessageIds: state.getIn(['chat_message_lists', pane.get('chat_id')], ImmutableOrderedSet()),
}); });
@ -26,6 +28,7 @@ class ChatWindow extends ImmutablePureComponent {
pane: ImmutablePropTypes.map.isRequired, pane: ImmutablePropTypes.map.isRequired,
idx: PropTypes.number, idx: PropTypes.number,
chatMessageIds: ImmutablePropTypes.orderedSet, chatMessageIds: ImmutablePropTypes.orderedSet,
chat: ImmutablePropTypes.map,
me: PropTypes.node, me: PropTypes.node,
} }
@ -88,12 +91,12 @@ class ChatWindow extends ImmutablePureComponent {
} }
render() { render() {
const { pane, idx, chatMessageIds } = this.props; const { pane, idx, chatMessageIds, chat } = this.props;
const chat = pane.get('chat');
const account = pane.getIn(['chat', 'account']); const account = pane.getIn(['chat', 'account']);
if (!chat || !account) return null; if (!chat || !account) return null;
const right = (285 * (idx + 1)) + 20; const right = (285 * (idx + 1)) + 20;
const unreadCount = chat.get('unread');
return ( return (
<div className={`pane pane--${pane.get('state')}`} style={{ right: `${right}px` }}> <div className={`pane pane--${pane.get('state')}`} style={{ right: `${right}px` }}>
@ -102,6 +105,7 @@ class ChatWindow extends ImmutablePureComponent {
<button className='pane__title' onClick={this.handleChatToggle(chat.get('id'))}> <button className='pane__title' onClick={this.handleChatToggle(chat.get('id'))}>
@{acctFull(account)} @{acctFull(account)}
</button> </button>
{unreadCount > 0 && <i className='icon-with-badge__badge'>{shortNumberFormat(unreadCount)}</i>}
<div className='pane__close'> <div className='pane__close'>
<IconButton icon='close' title='Close chat' onClick={this.handleChatClose(chat.get('id'))} /> <IconButton icon='close' title='Close chat' onClick={this.handleChatClose(chat.get('id'))} />
</div> </div>

Wyświetl plik

@ -67,6 +67,11 @@
.pane__close { .pane__close {
margin-left: auto; margin-left: auto;
} }
.icon-with-badge__badge {
position: static;
pointer-events: none;
}
} }
&__content { &__content {
@ -142,4 +147,15 @@
background: transparent; background: transparent;
align-items: start; align-items: start;
} }
.account__display-name {
position: relative;
}
.icon-with-badge__badge {
top: 0;
right: 0;
left: auto;
bottom: auto;
}
} }