diff --git a/app/soapbox/features/chats/chat_room.js b/app/soapbox/features/chats/chat_room.js
index e6df1953d..4a8c480ea 100644
--- a/app/soapbox/features/chats/chat_room.js
+++ b/app/soapbox/features/chats/chat_room.js
@@ -6,18 +6,20 @@ import { injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Avatar from 'soapbox/components/avatar';
import { acctFull } from 'soapbox/utils/accounts';
-import { fetchChat } from 'soapbox/actions/chats';
+import { fetchChat, markChatRead } from 'soapbox/actions/chats';
import ChatBox from './components/chat_box';
import Column from 'soapbox/components/column';
import ColumnBackButton from 'soapbox/components/column_back_button';
+import { Map as ImmutableMap } from 'immutable';
import { makeGetChat } from 'soapbox/selectors';
const mapStateToProps = (state, { params }) => {
const getChat = makeGetChat();
+ const chat = state.getIn(['chats', params.chatId], ImmutableMap()).toJS();
return {
me: state.get('me'),
- chat: getChat(state, { id: params.chatId }),
+ chat: getChat(state, chat),
};
};
@@ -42,9 +44,26 @@ class ChatRoom extends ImmutablePureComponent {
this.inputElem.focus();
}
+ markRead = () => {
+ const { dispatch, chat } = this.props;
+ if (!chat) return;
+ dispatch(markChatRead(chat.get('id')));
+ }
+
componentDidMount() {
const { dispatch, params } = this.props;
dispatch(fetchChat(params.chatId));
+ this.markRead();
+ }
+
+ componentDidUpdate(prevProps) {
+ const markReadConditions = [
+ () => this.props.chat !== undefined,
+ () => this.props.chat.get('unread') > 0,
+ ];
+
+ if (markReadConditions.every(c => c() === true))
+ this.markRead();
}
render() {
diff --git a/app/soapbox/features/chats/components/chat_box.js b/app/soapbox/features/chats/components/chat_box.js
index 0f1de7dbb..40123ca25 100644
--- a/app/soapbox/features/chats/components/chat_box.js
+++ b/app/soapbox/features/chats/components/chat_box.js
@@ -40,11 +40,24 @@ class ChatBox extends ImmutablePureComponent {
content: '',
}
- handleKeyDown = (e) => {
+ sendMessage = () => {
const { chatId } = this.props;
- if (e.key === 'Enter') {
- this.props.dispatch(sendChatMessage(chatId, this.state));
- this.setState({ content: '' });
+ if (this.state.content.length < 1) return;
+ this.props.dispatch(sendChatMessage(chatId, this.state));
+ this.setState({ content: '' });
+ }
+
+ insertLine = () => {
+ const { content } = this.state;
+ this.setState({ content: content + '\n' });
+ }
+
+ handleKeyDown = (e) => {
+ if (e.key === 'Enter' && e.shiftKey) {
+ this.insertLine();
+ e.preventDefault();
+ } else if (e.key === 'Enter') {
+ this.sendMessage();
e.preventDefault();
}
}
diff --git a/app/soapbox/features/chats/components/chat_list.js b/app/soapbox/features/chats/components/chat_list.js
index 41aae6397..e24d31ab9 100644
--- a/app/soapbox/features/chats/components/chat_list.js
+++ b/app/soapbox/features/chats/components/chat_list.js
@@ -3,7 +3,6 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { fetchChats } from 'soapbox/actions/chats';
import Chat from './chat';
import { makeGetChat } from 'soapbox/selectors';
@@ -42,10 +41,6 @@ class ChatList extends ImmutablePureComponent {
emptyMessage: PropTypes.node,
};
- componentDidMount() {
- this.props.dispatch(fetchChats());
- }
-
render() {
const { chats, emptyMessage } = this.props;
diff --git a/app/soapbox/features/chats/components/chat_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js
index 8e52e3270..e2fe305bd 100644
--- a/app/soapbox/features/chats/components/chat_message_list.js
+++ b/app/soapbox/features/chats/components/chat_message_list.js
@@ -4,9 +4,14 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { List as ImmutableList } from 'immutable';
+import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import emojify from 'soapbox/features/emoji/emoji';
import classNames from 'classnames';
+import { escape } from 'lodash';
+
+const makeEmojiMap = record => record.get('emojis', ImmutableList()).reduce((map, emoji) => {
+ return map.set(`:${emoji.get('shortcode')}:`, emoji);
+}, ImmutableMap());
const mapStateToProps = (state, { chatMessageIds }) => ({
me: state.get('me'),
@@ -72,6 +77,18 @@ class ChatMessageList extends ImmutablePureComponent {
this.scrollToBottom();
}
+ parsePendingContent = content => {
+ return escape(content).replace(/(?:\r\n|\r|\n)/g, '
');
+ }
+
+ parseContent = chatMessage => {
+ const content = chatMessage.get('content') || '';
+ const pending = chatMessage.get('pending', false);
+ const formatted = pending ? this.parsePendingContent(content) : content;
+ const emojiMap = makeEmojiMap(chatMessage);
+ return emojify(formatted, emojiMap.toJS());
+ }
+
render() {
const { chatMessages, me } = this.props;
@@ -88,7 +105,7 @@ class ChatMessageList extends ImmutablePureComponent {
diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js
index 59269d577..ff80086ee 100644
--- a/app/soapbox/features/ui/index.js
+++ b/app/soapbox/features/ui/index.js
@@ -18,6 +18,7 @@ import { expandHomeTimeline } from '../../actions/timelines';
import { expandNotifications } from '../../actions/notifications';
import { fetchReports } from '../../actions/admin';
import { fetchFilters } from '../../actions/filters';
+import { fetchChats } from 'soapbox/actions/chats';
import { clearHeight } from '../../actions/height_cache';
import { openModal } from '../../actions/modal';
import { WrappedRoute } from './util/react_router_helpers';
@@ -433,6 +434,7 @@ class UI extends React.PureComponent {
if (account) {
this.props.dispatch(expandHomeTimeline());
this.props.dispatch(expandNotifications());
+ this.props.dispatch(fetchChats());
// this.props.dispatch(fetchGroups('member'));
if (isStaff(account))
this.props.dispatch(fetchReports({ state: 'open' }));
diff --git a/app/styles/chats.scss b/app/styles/chats.scss
index 7ae51847d..011543ca3 100644
--- a/app/styles/chats.scss
+++ b/app/styles/chats.scss
@@ -113,6 +113,8 @@
background-color: var(--background-color);
overflow: hidden;
text-overflow: ellipsis;
+ overflow-wrap: break-word;
+ white-space: break-spaces;
a {
color: var(--brand-color--hicontrast);