From f9d7da0d51d1681810f0444996f87a27476d8014 Mon Sep 17 00:00:00 2001 From: Sean King Date: Sun, 30 Aug 2020 23:09:02 -0600 Subject: [PATCH 01/13] Add bookmark button to detailed status action bar view --- app/soapbox/features/status/components/action_bar.js | 12 +++++++++++- .../status/containers/detailed_status_container.js | 10 ++++++++++ app/soapbox/features/status/index.js | 11 +++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/soapbox/features/status/components/action_bar.js b/app/soapbox/features/status/components/action_bar.js index c5db0cab5..886e1a2b4 100644 --- a/app/soapbox/features/status/components/action_bar.js +++ b/app/soapbox/features/status/components/action_bar.js @@ -34,6 +34,8 @@ const messages = defineMessages({ admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, admin_status: { id: 'status.admin_status', defaultMessage: 'Open this post in the moderation interface' }, copy: { id: 'status.copy', defaultMessage: 'Copy link to post' }, + bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' }, + unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' }, }); const mapStateToProps = state => { @@ -63,6 +65,7 @@ class ActionBar extends React.PureComponent { onFavourite: PropTypes.func.isRequired, onEmojiReact: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, + onBookmark: PropTypes.func, onDirect: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, onMute: PropTypes.func, @@ -103,6 +106,10 @@ class ActionBar extends React.PureComponent { } } + handleBookmarkClick = () => { + this.props.onBookmark(this.props.status); + } + handleFavouriteClick = () => { const { me } = this.props; if (me) { @@ -237,9 +244,12 @@ class ActionBar extends React.PureComponent { if (publicStatus) { menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy }); // menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); - menu.push(null); } + menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), action: this.handleBookmarkClick }); + + menu.push(null); + if (me === status.getIn(['account', 'id'])) { if (publicStatus) { menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick }); diff --git a/app/soapbox/features/status/containers/detailed_status_container.js b/app/soapbox/features/status/containers/detailed_status_container.js index 7c78a2e4e..509587636 100644 --- a/app/soapbox/features/status/containers/detailed_status_container.js +++ b/app/soapbox/features/status/containers/detailed_status_container.js @@ -12,6 +12,8 @@ import { favourite, unreblog, unfavourite, + bookmark, + unbookmark, pin, unpin, } from '../../../actions/interactions'; @@ -88,6 +90,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }); }, + onBookmark(status) { + if (status.get('bookmarked')) { + dispatch(unbookmark(status)); + } else { + dispatch(bookmark(status)); + } + }, + onFavourite(status) { if (status.get('favourited')) { dispatch(unfavourite(status)); diff --git a/app/soapbox/features/status/index.js b/app/soapbox/features/status/index.js index 8eb3530f6..d82f8c7a1 100644 --- a/app/soapbox/features/status/index.js +++ b/app/soapbox/features/status/index.js @@ -14,6 +14,8 @@ import { unfavourite, reblog, unreblog, + bookmark, + unbookmark, pin, unpin, } from '../../actions/interactions'; @@ -168,6 +170,14 @@ class Status extends ImmutablePureComponent { } } + handleBookmark = (status) => { + if (status.get('bookmarked')) { + this.props.dispatch(unbookmark(status)); + } else { + this.props.dispatch(bookmark(status)); + } + } + handleReplyClick = (status) => { let { askReplyConfirmation, dispatch, intl } = this.props; if (askReplyConfirmation) { @@ -507,6 +517,7 @@ class Status extends ImmutablePureComponent { onBlock={this.handleBlockClick} onReport={this.handleReport} onPin={this.handlePin} + onBookmark={this.handleBookmark} onEmbed={this.handleEmbed} /> From b337a4560ec9e57d461be9eb44fc057d3c4bd3bc Mon Sep 17 00:00:00 2001 From: Curtis ROck Date: Mon, 31 Aug 2020 22:00:11 -0500 Subject: [PATCH 02/13] Apply non-blank default BrandColor only when API and soapbox.json methods fail, and only when API and/or JSON method succeeds, but brandColor value is blank --- app/soapbox/actions/soapbox.js | 10 ++++++++-- app/soapbox/reducers/soapbox.js | 10 +++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/soapbox/actions/soapbox.js b/app/soapbox/actions/soapbox.js index eedd1787f..f975bf848 100644 --- a/app/soapbox/actions/soapbox.js +++ b/app/soapbox/actions/soapbox.js @@ -7,7 +7,7 @@ export const SOAPBOX_CONFIG_REQUEST_FAIL = 'SOAPBOX_CONFIG_REQUEST_FAIL'; export const defaultConfig = ImmutableMap({ logo: '', banner: '', - brandColor: '#0482d8', // Azure + brandColor: '', // Empty customCss: ImmutableList(), promoPanel: ImmutableMap({ items: ImmutableList(), @@ -48,7 +48,13 @@ export function fetchSoapboxJson() { }; } -export function importSoapboxConfig(soapboxConfig) { +export function importSoapboxConfig(soapboxConfig, getIn) { + if(soapboxConfig.get('brandColor') === '') { + const defaultBrandColor = ImmutableMap({ + brandColor: '#0482d8', // Azure + }); + defaultBrandColor.mergeDeep(soapboxConfig); + }; return { type: SOAPBOX_CONFIG_REQUEST_SUCCESS, soapboxConfig, diff --git a/app/soapbox/reducers/soapbox.js b/app/soapbox/reducers/soapbox.js index dd7b0bea3..c58b22ddb 100644 --- a/app/soapbox/reducers/soapbox.js +++ b/app/soapbox/reducers/soapbox.js @@ -1,5 +1,8 @@ import { ADMIN_CONFIG_UPDATE_SUCCESS } from '../actions/admin'; -import { SOAPBOX_CONFIG_REQUEST_SUCCESS } from '../actions/soapbox'; +import { + SOAPBOX_CONFIG_REQUEST_SUCCESS, + SOAPBOX_CONFIG_REQUEST_FAIL, +} from '../actions/soapbox'; import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; import { ConfigDB } from 'soapbox/utils/config_db'; @@ -22,6 +25,11 @@ export default function soapbox(state = initialState, action) { switch(action.type) { case SOAPBOX_CONFIG_REQUEST_SUCCESS: return fromJS(action.soapboxConfig); + case SOAPBOX_CONFIG_REQUEST_FAIL: + const defaultBrandColor = ImmutableMap({ + brandColor: '#0482d8', // Azure + }); + return defaultBrandColor.mergeDeep(state.get('soapbox')); case ADMIN_CONFIG_UPDATE_SUCCESS: return updateFromAdmin(state, fromJS(action.config)); default: From 181eef1edd0fd67693940665d82251f1efa51d55 Mon Sep 17 00:00:00 2001 From: Curtis ROck Date: Wed, 2 Sep 2020 21:47:46 -0500 Subject: [PATCH 03/13] corrected errors --- app/soapbox/actions/soapbox.js | 9 +++------ app/soapbox/reducers/soapbox.js | 9 +++++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/soapbox/actions/soapbox.js b/app/soapbox/actions/soapbox.js index f975bf848..e6cced78b 100644 --- a/app/soapbox/actions/soapbox.js +++ b/app/soapbox/actions/soapbox.js @@ -48,12 +48,9 @@ export function fetchSoapboxJson() { }; } -export function importSoapboxConfig(soapboxConfig, getIn) { - if(soapboxConfig.get('brandColor') === '') { - const defaultBrandColor = ImmutableMap({ - brandColor: '#0482d8', // Azure - }); - defaultBrandColor.mergeDeep(soapboxConfig); +export function importSoapboxConfig(soapboxConfig) { + if (!soapboxConfig.brandColor) { + soapboxConfig.brandColor = '#0482d8'; }; return { type: SOAPBOX_CONFIG_REQUEST_SUCCESS, diff --git a/app/soapbox/reducers/soapbox.js b/app/soapbox/reducers/soapbox.js index c58b22ddb..3e448add2 100644 --- a/app/soapbox/reducers/soapbox.js +++ b/app/soapbox/reducers/soapbox.js @@ -8,6 +8,10 @@ import { ConfigDB } from 'soapbox/utils/config_db'; const initialState = ImmutableMap(); +const fallbackState = ImmutableMap({ + brandColor: '#0482d8', // Azure +}); + const updateFromAdmin = (state, config) => { const configs = config.get('configs', ImmutableList()); @@ -26,10 +30,7 @@ export default function soapbox(state = initialState, action) { case SOAPBOX_CONFIG_REQUEST_SUCCESS: return fromJS(action.soapboxConfig); case SOAPBOX_CONFIG_REQUEST_FAIL: - const defaultBrandColor = ImmutableMap({ - brandColor: '#0482d8', // Azure - }); - return defaultBrandColor.mergeDeep(state.get('soapbox')); + return fallbackState.mergeDeep(state.get('soapbox')); case ADMIN_CONFIG_UPDATE_SUCCESS: return updateFromAdmin(state, fromJS(action.config)); default: From 4b1606e8dde1170705c514d8cecb8a84e99abb41 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 2 Sep 2020 22:38:04 -0500 Subject: [PATCH 04/13] Favicon: refactor, show domain in alt/title --- app/soapbox/components/status.js | 7 ++++-- .../status/components/detailed_status.js | 7 ++++-- app/soapbox/utils/accounts.js | 25 +++++++++++-------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/soapbox/components/status.js b/app/soapbox/components/status.js index ffca8efeb..e03c4399d 100644 --- a/app/soapbox/components/status.js +++ b/app/soapbox/components/status.js @@ -21,6 +21,7 @@ import { NavLink } from 'react-router-dom'; import ProfileHoverCardContainer from '../features/profile_hover_card/profile_hover_card_container'; import { isMobile } from '../../../app/soapbox/is_mobile'; import { debounce } from 'lodash'; +import { getDomain } from 'soapbox/utils/accounts'; // We use the component (and not the container) since we do not want // to use the progress bar to show download progress @@ -455,6 +456,8 @@ class Status extends ImmutablePureComponent { const statusUrl = `/@${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`; const { profileCardVisible } = this.state; + const favicon = status.getIn(['account', 'pleroma', 'favicon']); + const domain = getDomain(status.get('account')); return ( @@ -468,9 +471,9 @@ class Status extends ImmutablePureComponent { - {status.hasIn(['account', 'pleroma', 'favicon']) && + {favicon &&
- + {domain}
}
diff --git a/app/soapbox/features/status/components/detailed_status.js b/app/soapbox/features/status/components/detailed_status.js index 454c22fba..3ff82a810 100644 --- a/app/soapbox/features/status/components/detailed_status.js +++ b/app/soapbox/features/status/components/detailed_status.js @@ -19,6 +19,7 @@ import { StatusInteractionBar } from './status_interaction_bar'; import ProfileHoverCardContainer from 'soapbox/features/profile_hover_card/profile_hover_card_container'; import { isMobile } from 'soapbox/is_mobile'; import { debounce } from 'lodash'; +import { getDomain } from 'soapbox/utils/accounts'; export default class DetailedStatus extends ImmutablePureComponent { @@ -103,6 +104,8 @@ export default class DetailedStatus extends ImmutablePureComponent { const outerStyle = { boxSizing: 'border-box' }; const { compact } = this.props; const { profileCardVisible } = this.state; + const favicon = status.getIn(['account', 'pleroma', 'favicon']); + const domain = getDomain(status.get('account')); if (!status) { return null; @@ -208,9 +211,9 @@ export default class DetailedStatus extends ImmutablePureComponent {
- {status.hasIn(['account', 'pleroma', 'favicon']) && + {favicon &&
- + {domain}
} {statusTypeIcon} diff --git a/app/soapbox/utils/accounts.js b/app/soapbox/utils/accounts.js index 3d04a3360..929429b24 100644 --- a/app/soapbox/utils/accounts.js +++ b/app/soapbox/utils/accounts.js @@ -1,21 +1,26 @@ import { Map as ImmutableMap } from 'immutable'; import { List as ImmutableList } from 'immutable'; +const guessDomain = account => { + try { + let re = /https?:\/\/(.*?)\//i; + return re.exec(account.get('url'))[1]; + } catch(e) { + return null; + } +}; + export const getDomain = account => { - let re = /https?:\/\/(.*?)\//i; - return re.exec(account.get('url'))[1]; + let domain = account.get('acct').split('@')[1]; + if (!domain) domain = guessDomain(account); + return domain; }; // user@domain even for local users export const acctFull = account => { - let [user, domain] = account.get('acct').split('@'); - try { - if (!domain) domain = getDomain(account); - } catch(e) { - console.warning('Could not get domain for acctFull. Falling back to acct.'); - return account.get('acct'); - } - return [user, domain].join('@'); + const [user, domain] = account.get('acct').split('@'); + if (!domain) return [user, guessDomain(account)].join('@'); + return account.get('acct'); }; export const isStaff = (account = ImmutableMap()) => ( From 865d251ae0a3098fc9a8faf03bdfb9dd4cf95061 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 00:26:50 -0500 Subject: [PATCH 05/13] Favicons: empty alt text --- app/soapbox/components/status.js | 2 +- app/soapbox/features/status/components/detailed_status.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/soapbox/components/status.js b/app/soapbox/components/status.js index e03c4399d..f8d46b043 100644 --- a/app/soapbox/components/status.js +++ b/app/soapbox/components/status.js @@ -473,7 +473,7 @@ class Status extends ImmutablePureComponent { {favicon &&
- {domain} +
}
diff --git a/app/soapbox/features/status/components/detailed_status.js b/app/soapbox/features/status/components/detailed_status.js index 3ff82a810..d58bd7e72 100644 --- a/app/soapbox/features/status/components/detailed_status.js +++ b/app/soapbox/features/status/components/detailed_status.js @@ -213,7 +213,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
{favicon &&
- {domain} +
} {statusTypeIcon}
From 91605d7d911f8eccbad7dae543488a98e2d0e750 Mon Sep 17 00:00:00 2001 From: crockwave Date: Thu, 3 Sep 2020 11:10:03 -0500 Subject: [PATCH 06/13] Fixed reducer error --- app/soapbox/reducers/soapbox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/reducers/soapbox.js b/app/soapbox/reducers/soapbox.js index 3e448add2..ecf1656f5 100644 --- a/app/soapbox/reducers/soapbox.js +++ b/app/soapbox/reducers/soapbox.js @@ -30,7 +30,7 @@ export default function soapbox(state = initialState, action) { case SOAPBOX_CONFIG_REQUEST_SUCCESS: return fromJS(action.soapboxConfig); case SOAPBOX_CONFIG_REQUEST_FAIL: - return fallbackState.mergeDeep(state.get('soapbox')); + return fallbackState.mergeDeep(state); case ADMIN_CONFIG_UPDATE_SUCCESS: return updateFromAdmin(state, fromJS(action.config)); default: From 3246812a728a22c9d2c8b81f422e3f83d13c5e11 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 13:02:26 -0500 Subject: [PATCH 07/13] Theme toggle: fix color in sidebar menu light mode --- app/styles/components/theme-toggle.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/styles/components/theme-toggle.scss b/app/styles/components/theme-toggle.scss index 1f2697b89..c0cadc68f 100644 --- a/app/styles/components/theme-toggle.scss +++ b/app/styles/components/theme-toggle.scss @@ -9,10 +9,6 @@ .react-toggle { vertical-align: middle; - &-track { - background-color: var(--foreground-color); - } - &-track-check, &-track-x { display: flex; From 35a0cdb64e99efcac00074492f78ac79af80898d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 13:03:30 -0500 Subject: [PATCH 08/13] Chats: fix chatroom title text color --- app/styles/chats.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/chats.scss b/app/styles/chats.scss index d6cb2bed8..7ae51847d 100644 --- a/app/styles/chats.scss +++ b/app/styles/chats.scss @@ -252,7 +252,7 @@ background: transparent; border: 0; padding: 0; - color: #fff; + color: var(--primary-text-color); font-weight: bold; text-align: left; font-size: 14px; From 2db5c67a497acde4234df796bc87a6617252185c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 13:48:15 -0500 Subject: [PATCH 09/13] Chats: parse custom emoji, #386 --- .../features/chats/components/chat_message_list.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/soapbox/features/chats/components/chat_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js index 8e52e3270..3888d9222 100644 --- a/app/soapbox/features/chats/components/chat_message_list.js +++ b/app/soapbox/features/chats/components/chat_message_list.js @@ -4,10 +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'; +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'), chatMessages: chatMessageIds.reduce((acc, curr) => { @@ -72,6 +76,11 @@ class ChatMessageList extends ImmutablePureComponent { this.scrollToBottom(); } + parseContent = chatMessage => { + const emojiMap = makeEmojiMap(chatMessage); + return emojify(chatMessage.get('content') || '', emojiMap.toJS()); + } + render() { const { chatMessages, me } = this.props; @@ -88,7 +97,7 @@ class ChatMessageList extends ImmutablePureComponent {
From 57fc08771ce46f85ad1fc28ab9b9f8b9fe8ea8ac Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 14:11:33 -0500 Subject: [PATCH 10/13] Chats: format content, fixes #382, related #380 --- .../features/chats/components/chat_box.js | 21 +++++++++++++++---- .../chats/components/chat_message_list.js | 10 ++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) 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_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js index 3888d9222..e2fe305bd 100644 --- a/app/soapbox/features/chats/components/chat_message_list.js +++ b/app/soapbox/features/chats/components/chat_message_list.js @@ -7,6 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; 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); @@ -76,9 +77,16 @@ 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(chatMessage.get('content') || '', emojiMap.toJS()); + return emojify(formatted, emojiMap.toJS()); } render() { From 9d7b86935f3299df58855db3faae339b8a7bb93b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 14:18:11 -0500 Subject: [PATCH 11/13] Chats: fetch chats in UI instead of chat list, fixes #384 --- app/soapbox/features/chats/components/chat_list.js | 5 ----- app/soapbox/features/ui/index.js | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) 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/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' })); From 9b55f813bb3a3604dd7c32fd15ce923c08be27d4 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 14:47:04 -0500 Subject: [PATCH 12/13] Chats: mark read more aggresively on mobile, fixes #367 --- app/soapbox/features/chats/chat_room.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) 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() { From 9df386b477009e0bc64f25e1baf8e9b8642ddc16 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 3 Sep 2020 14:57:58 -0500 Subject: [PATCH 13/13] Chats: fix #375 truncated message text --- app/styles/chats.scss | 2 ++ 1 file changed, 2 insertions(+) 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);