From 81ef21a0c802f1d905f37a2a818544a8b400793c Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Sat, 25 Feb 2023 14:34:32 +0100 Subject: [Glitch] Rename JSX files with proper `.jsx` extension Port 44a7d87cb1f5df953b6c14c16c59e2e4ead1bcb9 to glitch-soc Signed-off-by: Claire --- .../direct_timeline/components/column_settings.js | 42 ---- .../direct_timeline/components/column_settings.jsx | 42 ++++ .../direct_timeline/components/conversation.js | 232 --------------------- .../direct_timeline/components/conversation.jsx | 232 +++++++++++++++++++++ .../components/conversations_list.js | 75 ------- .../components/conversations_list.jsx | 75 +++++++ .../glitch/features/direct_timeline/index.js | 156 -------------- .../glitch/features/direct_timeline/index.jsx | 156 ++++++++++++++ 8 files changed, 505 insertions(+), 505 deletions(-) delete mode 100644 app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js create mode 100644 app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.jsx delete mode 100644 app/javascript/flavours/glitch/features/direct_timeline/components/conversation.js create mode 100644 app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx delete mode 100644 app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.js create mode 100644 app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.jsx delete mode 100644 app/javascript/flavours/glitch/features/direct_timeline/index.js create mode 100644 app/javascript/flavours/glitch/features/direct_timeline/index.jsx (limited to 'app/javascript/flavours/glitch/features/direct_timeline') diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js b/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js deleted file mode 100644 index 18c3c7e21..000000000 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import SettingToggle from 'flavours/glitch/features/notifications/components/setting_toggle'; -import SettingText from '../../../components/setting_text'; - -const messages = defineMessages({ - filter_regex: { id: 'home.column_settings.filter_regex', defaultMessage: 'Filter out by regular expressions' }, - settings: { id: 'home.settings', defaultMessage: 'Column settings' }, -}); - -export default @injectIntl -class ColumnSettings extends React.PureComponent { - - static propTypes = { - settings: ImmutablePropTypes.map.isRequired, - onChange: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - }; - - render () { - const { settings, onChange, intl } = this.props; - - return ( -
- - -
- } /> -
- - - -
- -
-
- ); - } - -} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.jsx new file mode 100644 index 000000000..18c3c7e21 --- /dev/null +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.jsx @@ -0,0 +1,42 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import SettingToggle from 'flavours/glitch/features/notifications/components/setting_toggle'; +import SettingText from '../../../components/setting_text'; + +const messages = defineMessages({ + filter_regex: { id: 'home.column_settings.filter_regex', defaultMessage: 'Filter out by regular expressions' }, + settings: { id: 'home.settings', defaultMessage: 'Column settings' }, +}); + +export default @injectIntl +class ColumnSettings extends React.PureComponent { + + static propTypes = { + settings: ImmutablePropTypes.map.isRequired, + onChange: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + render () { + const { settings, onChange, intl } = this.props; + + return ( +
+ + +
+ } /> +
+ + + +
+ +
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.js b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.js deleted file mode 100644 index ad2a68ebd..000000000 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.js +++ /dev/null @@ -1,232 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import StatusContent from 'flavours/glitch/components/status_content'; -import AttachmentList from 'flavours/glitch/components/attachment_list'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; -import AvatarComposite from 'flavours/glitch/components/avatar_composite'; -import Permalink from 'flavours/glitch/components/permalink'; -import IconButton from 'flavours/glitch/components/icon_button'; -import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp'; -import { HotKeys } from 'react-hotkeys'; -import { autoPlayGif } from 'flavours/glitch/initial_state'; -import classNames from 'classnames'; - -const messages = defineMessages({ - more: { id: 'status.more', defaultMessage: 'More' }, - open: { id: 'conversation.open', defaultMessage: 'View conversation' }, - reply: { id: 'status.reply', defaultMessage: 'Reply' }, - markAsRead: { id: 'conversation.mark_as_read', defaultMessage: 'Mark as read' }, - delete: { id: 'conversation.delete', defaultMessage: 'Delete conversation' }, - muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' }, - unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' }, -}); - -export default @injectIntl -class Conversation extends ImmutablePureComponent { - - static contextTypes = { - router: PropTypes.object, - }; - - static propTypes = { - conversationId: PropTypes.string.isRequired, - accounts: ImmutablePropTypes.list.isRequired, - lastStatus: ImmutablePropTypes.map, - unread:PropTypes.bool.isRequired, - scrollKey: PropTypes.string, - onMoveUp: PropTypes.func, - onMoveDown: PropTypes.func, - markRead: PropTypes.func.isRequired, - delete: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - }; - - state = { - isExpanded: undefined, - }; - - parseClick = (e, destination) => { - const { router } = this.context; - const { lastStatus, unread, markRead } = this.props; - if (!router) return; - - if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) { - if (destination === undefined) { - if (unread) { - markRead(); - } - destination = `/statuses/${lastStatus.get('id')}`; - } - let state = { ...router.history.location.state }; - state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; - router.history.push(destination, state); - e.preventDefault(); - } - }; - - handleMouseEnter = ({ currentTarget }) => { - if (autoPlayGif) { - return; - } - - const emojis = currentTarget.querySelectorAll('.custom-emoji'); - - for (var i = 0; i < emojis.length; i++) { - let emoji = emojis[i]; - emoji.src = emoji.getAttribute('data-original'); - } - }; - - handleMouseLeave = ({ currentTarget }) => { - if (autoPlayGif) { - return; - } - - const emojis = currentTarget.querySelectorAll('.custom-emoji'); - - for (var i = 0; i < emojis.length; i++) { - let emoji = emojis[i]; - emoji.src = emoji.getAttribute('data-static'); - } - }; - - handleClick = () => { - if (!this.context.router) { - return; - } - - const { lastStatus, unread, markRead } = this.props; - - if (unread) { - markRead(); - } - - this.context.router.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`); - }; - - handleMarkAsRead = () => { - this.props.markRead(); - }; - - handleReply = () => { - this.props.reply(this.props.lastStatus, this.context.router.history); - }; - - handleDelete = () => { - this.props.delete(); - }; - - handleHotkeyMoveUp = () => { - this.props.onMoveUp(this.props.conversationId); - }; - - handleHotkeyMoveDown = () => { - this.props.onMoveDown(this.props.conversationId); - }; - - handleConversationMute = () => { - this.props.onMute(this.props.lastStatus); - }; - - handleShowMore = () => { - this.props.onToggleHidden(this.props.lastStatus); - - if (this.props.lastStatus.get('spoiler_text')) { - this.setExpansion(!this.state.isExpanded); - } - }; - - setExpansion = value => { - this.setState({ isExpanded: value }); - }; - - render () { - const { accounts, lastStatus, unread, scrollKey, intl } = this.props; - - if (lastStatus === null) { - return null; - } - - const isExpanded = this.props.settings.getIn(['content_warnings', 'shared_state']) ? !lastStatus.get('hidden') : this.state.isExpanded; - - const menu = [ - { text: intl.formatMessage(messages.open), action: this.handleClick }, - null, - ]; - - menu.push({ text: intl.formatMessage(lastStatus.get('muted') ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMute }); - - if (unread) { - menu.push({ text: intl.formatMessage(messages.markAsRead), action: this.handleMarkAsRead }); - menu.push(null); - } - - menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDelete }); - - const names = accounts.map(a => ).reduce((prev, cur) => [prev, ', ', cur]); - - const handlers = { - reply: this.handleReply, - open: this.handleClick, - moveUp: this.handleHotkeyMoveUp, - moveDown: this.handleHotkeyMoveDown, - toggleHidden: this.handleShowMore, - }; - - let media = null; - if (lastStatus.get('media_attachments').size > 0) { - media = ; - } - - return ( - -
-
- -
- -
-
-
- {unread && } -
- -
- {names} }} /> -
-
- - - -
- - -
- -
-
-
-
-
- ); - } - -} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx new file mode 100644 index 000000000..ad2a68ebd --- /dev/null +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/conversation.jsx @@ -0,0 +1,232 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import StatusContent from 'flavours/glitch/components/status_content'; +import AttachmentList from 'flavours/glitch/components/attachment_list'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; +import AvatarComposite from 'flavours/glitch/components/avatar_composite'; +import Permalink from 'flavours/glitch/components/permalink'; +import IconButton from 'flavours/glitch/components/icon_button'; +import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp'; +import { HotKeys } from 'react-hotkeys'; +import { autoPlayGif } from 'flavours/glitch/initial_state'; +import classNames from 'classnames'; + +const messages = defineMessages({ + more: { id: 'status.more', defaultMessage: 'More' }, + open: { id: 'conversation.open', defaultMessage: 'View conversation' }, + reply: { id: 'status.reply', defaultMessage: 'Reply' }, + markAsRead: { id: 'conversation.mark_as_read', defaultMessage: 'Mark as read' }, + delete: { id: 'conversation.delete', defaultMessage: 'Delete conversation' }, + muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' }, + unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' }, +}); + +export default @injectIntl +class Conversation extends ImmutablePureComponent { + + static contextTypes = { + router: PropTypes.object, + }; + + static propTypes = { + conversationId: PropTypes.string.isRequired, + accounts: ImmutablePropTypes.list.isRequired, + lastStatus: ImmutablePropTypes.map, + unread:PropTypes.bool.isRequired, + scrollKey: PropTypes.string, + onMoveUp: PropTypes.func, + onMoveDown: PropTypes.func, + markRead: PropTypes.func.isRequired, + delete: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + state = { + isExpanded: undefined, + }; + + parseClick = (e, destination) => { + const { router } = this.context; + const { lastStatus, unread, markRead } = this.props; + if (!router) return; + + if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) { + if (destination === undefined) { + if (unread) { + markRead(); + } + destination = `/statuses/${lastStatus.get('id')}`; + } + let state = { ...router.history.location.state }; + state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; + router.history.push(destination, state); + e.preventDefault(); + } + }; + + handleMouseEnter = ({ currentTarget }) => { + if (autoPlayGif) { + return; + } + + const emojis = currentTarget.querySelectorAll('.custom-emoji'); + + for (var i = 0; i < emojis.length; i++) { + let emoji = emojis[i]; + emoji.src = emoji.getAttribute('data-original'); + } + }; + + handleMouseLeave = ({ currentTarget }) => { + if (autoPlayGif) { + return; + } + + const emojis = currentTarget.querySelectorAll('.custom-emoji'); + + for (var i = 0; i < emojis.length; i++) { + let emoji = emojis[i]; + emoji.src = emoji.getAttribute('data-static'); + } + }; + + handleClick = () => { + if (!this.context.router) { + return; + } + + const { lastStatus, unread, markRead } = this.props; + + if (unread) { + markRead(); + } + + this.context.router.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`); + }; + + handleMarkAsRead = () => { + this.props.markRead(); + }; + + handleReply = () => { + this.props.reply(this.props.lastStatus, this.context.router.history); + }; + + handleDelete = () => { + this.props.delete(); + }; + + handleHotkeyMoveUp = () => { + this.props.onMoveUp(this.props.conversationId); + }; + + handleHotkeyMoveDown = () => { + this.props.onMoveDown(this.props.conversationId); + }; + + handleConversationMute = () => { + this.props.onMute(this.props.lastStatus); + }; + + handleShowMore = () => { + this.props.onToggleHidden(this.props.lastStatus); + + if (this.props.lastStatus.get('spoiler_text')) { + this.setExpansion(!this.state.isExpanded); + } + }; + + setExpansion = value => { + this.setState({ isExpanded: value }); + }; + + render () { + const { accounts, lastStatus, unread, scrollKey, intl } = this.props; + + if (lastStatus === null) { + return null; + } + + const isExpanded = this.props.settings.getIn(['content_warnings', 'shared_state']) ? !lastStatus.get('hidden') : this.state.isExpanded; + + const menu = [ + { text: intl.formatMessage(messages.open), action: this.handleClick }, + null, + ]; + + menu.push({ text: intl.formatMessage(lastStatus.get('muted') ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMute }); + + if (unread) { + menu.push({ text: intl.formatMessage(messages.markAsRead), action: this.handleMarkAsRead }); + menu.push(null); + } + + menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDelete }); + + const names = accounts.map(a => ).reduce((prev, cur) => [prev, ', ', cur]); + + const handlers = { + reply: this.handleReply, + open: this.handleClick, + moveUp: this.handleHotkeyMoveUp, + moveDown: this.handleHotkeyMoveDown, + toggleHidden: this.handleShowMore, + }; + + let media = null; + if (lastStatus.get('media_attachments').size > 0) { + media = ; + } + + return ( + +
+
+ +
+ +
+
+
+ {unread && } +
+ +
+ {names} }} /> +
+
+ + + +
+ + +
+ +
+
+
+
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.js b/app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.js deleted file mode 100644 index ae72179e2..000000000 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.js +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ConversationContainer from '../containers/conversation_container'; -import ScrollableList from 'flavours/glitch/components/scrollable_list'; -import { debounce } from 'lodash'; - -export default class ConversationsList extends ImmutablePureComponent { - - static propTypes = { - conversations: ImmutablePropTypes.list.isRequired, - scrollKey: PropTypes.string.isRequired, - hasMore: PropTypes.bool, - isLoading: PropTypes.bool, - onLoadMore: PropTypes.func, - }; - - getCurrentIndex = id => this.props.conversations.findIndex(x => x.get('id') === id); - - handleMoveUp = id => { - const elementIndex = this.getCurrentIndex(id) - 1; - this._selectChild(elementIndex, true); - }; - - handleMoveDown = id => { - const elementIndex = this.getCurrentIndex(id) + 1; - this._selectChild(elementIndex, false); - }; - - _selectChild (index, align_top) { - const container = this.node.node; - const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`); - - if (element) { - if (align_top && container.scrollTop > element.offsetTop) { - element.scrollIntoView(true); - } else if (!align_top && container.scrollTop + container.clientHeight < element.offsetTop + element.offsetHeight) { - element.scrollIntoView(false); - } - element.focus(); - } - } - - setRef = c => { - this.node = c; - }; - - handleLoadOlder = debounce(() => { - const last = this.props.conversations.last(); - - if (last && last.get('last_status')) { - this.props.onLoadMore(last.get('last_status')); - } - }, 300, { leading: true }); - - render () { - const { conversations, onLoadMore, ...other } = this.props; - - return ( - - {conversations.map(item => ( - - ))} - - ); - } - -} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.jsx b/app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.jsx new file mode 100644 index 000000000..ae72179e2 --- /dev/null +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/conversations_list.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ConversationContainer from '../containers/conversation_container'; +import ScrollableList from 'flavours/glitch/components/scrollable_list'; +import { debounce } from 'lodash'; + +export default class ConversationsList extends ImmutablePureComponent { + + static propTypes = { + conversations: ImmutablePropTypes.list.isRequired, + scrollKey: PropTypes.string.isRequired, + hasMore: PropTypes.bool, + isLoading: PropTypes.bool, + onLoadMore: PropTypes.func, + }; + + getCurrentIndex = id => this.props.conversations.findIndex(x => x.get('id') === id); + + handleMoveUp = id => { + const elementIndex = this.getCurrentIndex(id) - 1; + this._selectChild(elementIndex, true); + }; + + handleMoveDown = id => { + const elementIndex = this.getCurrentIndex(id) + 1; + this._selectChild(elementIndex, false); + }; + + _selectChild (index, align_top) { + const container = this.node.node; + const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`); + + if (element) { + if (align_top && container.scrollTop > element.offsetTop) { + element.scrollIntoView(true); + } else if (!align_top && container.scrollTop + container.clientHeight < element.offsetTop + element.offsetHeight) { + element.scrollIntoView(false); + } + element.focus(); + } + } + + setRef = c => { + this.node = c; + }; + + handleLoadOlder = debounce(() => { + const last = this.props.conversations.last(); + + if (last && last.get('last_status')) { + this.props.onLoadMore(last.get('last_status')); + } + }, 300, { leading: true }); + + render () { + const { conversations, onLoadMore, ...other } = this.props; + + return ( + + {conversations.map(item => ( + + ))} + + ); + } + +} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/index.js b/app/javascript/flavours/glitch/features/direct_timeline/index.js deleted file mode 100644 index afd348988..000000000 --- a/app/javascript/flavours/glitch/features/direct_timeline/index.js +++ /dev/null @@ -1,156 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { Helmet } from 'react-helmet'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; -import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns'; -import { mountConversations, unmountConversations, expandConversations } from 'flavours/glitch/actions/conversations'; -import { connectDirectStream } from 'flavours/glitch/actions/streaming'; -import { expandDirectTimeline } from 'flavours/glitch/actions/timelines'; -import Column from 'flavours/glitch/components/column'; -import ColumnHeader from 'flavours/glitch/components/column_header'; -import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container'; -import ColumnSettingsContainer from './containers/column_settings_container'; -import ConversationsListContainer from './containers/conversations_list_container'; - -const messages = defineMessages({ - title: { id: 'column.direct', defaultMessage: 'Direct messages' }, -}); - -const mapStateToProps = state => ({ - hasUnread: state.getIn(['timelines', 'direct', 'unread']) > 0, - conversationsMode: state.getIn(['settings', 'direct', 'conversations']), -}); - -export default @connect(mapStateToProps) -@injectIntl -class DirectTimeline extends React.PureComponent { - - static propTypes = { - dispatch: PropTypes.func.isRequired, - columnId: PropTypes.string, - intl: PropTypes.object.isRequired, - hasUnread: PropTypes.bool, - multiColumn: PropTypes.bool, - conversationsMode: PropTypes.bool, - }; - - handlePin = () => { - const { columnId, dispatch } = this.props; - - if (columnId) { - dispatch(removeColumn(columnId)); - } else { - dispatch(addColumn('DIRECT', {})); - } - }; - - handleMove = (dir) => { - const { columnId, dispatch } = this.props; - dispatch(moveColumn(columnId, dir)); - }; - - handleHeaderClick = () => { - this.column.scrollTop(); - }; - - componentDidMount () { - const { dispatch, conversationsMode } = this.props; - - dispatch(mountConversations()); - - if (conversationsMode) { - dispatch(expandConversations()); - } else { - dispatch(expandDirectTimeline()); - } - - this.disconnect = dispatch(connectDirectStream()); - } - - componentDidUpdate(prevProps) { - const { dispatch, conversationsMode } = this.props; - - if (prevProps.conversationsMode && !conversationsMode) { - dispatch(expandDirectTimeline()); - } else if (!prevProps.conversationsMode && conversationsMode) { - dispatch(expandConversations()); - } - } - - componentWillUnmount () { - this.props.dispatch(unmountConversations()); - - if (this.disconnect) { - this.disconnect(); - this.disconnect = null; - } - } - - setRef = c => { - this.column = c; - }; - - handleLoadMoreTimeline = maxId => { - this.props.dispatch(expandDirectTimeline({ maxId })); - }; - - handleLoadMoreConversations = maxId => { - this.props.dispatch(expandConversations({ maxId })); - }; - - render () { - const { intl, hasUnread, columnId, multiColumn, conversationsMode } = this.props; - const pinned = !!columnId; - - let contents; - if (conversationsMode) { - contents = ( - } - emptyMessage={} - /> - ); - } else { - contents = ( - } - emptyMessage={} - /> - ); - } - - return ( - - - - - - {contents} - - - {intl.formatMessage(messages.title)} - - - - ); - } - -} diff --git a/app/javascript/flavours/glitch/features/direct_timeline/index.jsx b/app/javascript/flavours/glitch/features/direct_timeline/index.jsx new file mode 100644 index 000000000..afd348988 --- /dev/null +++ b/app/javascript/flavours/glitch/features/direct_timeline/index.jsx @@ -0,0 +1,156 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { Helmet } from 'react-helmet'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns'; +import { mountConversations, unmountConversations, expandConversations } from 'flavours/glitch/actions/conversations'; +import { connectDirectStream } from 'flavours/glitch/actions/streaming'; +import { expandDirectTimeline } from 'flavours/glitch/actions/timelines'; +import Column from 'flavours/glitch/components/column'; +import ColumnHeader from 'flavours/glitch/components/column_header'; +import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container'; +import ColumnSettingsContainer from './containers/column_settings_container'; +import ConversationsListContainer from './containers/conversations_list_container'; + +const messages = defineMessages({ + title: { id: 'column.direct', defaultMessage: 'Direct messages' }, +}); + +const mapStateToProps = state => ({ + hasUnread: state.getIn(['timelines', 'direct', 'unread']) > 0, + conversationsMode: state.getIn(['settings', 'direct', 'conversations']), +}); + +export default @connect(mapStateToProps) +@injectIntl +class DirectTimeline extends React.PureComponent { + + static propTypes = { + dispatch: PropTypes.func.isRequired, + columnId: PropTypes.string, + intl: PropTypes.object.isRequired, + hasUnread: PropTypes.bool, + multiColumn: PropTypes.bool, + conversationsMode: PropTypes.bool, + }; + + handlePin = () => { + const { columnId, dispatch } = this.props; + + if (columnId) { + dispatch(removeColumn(columnId)); + } else { + dispatch(addColumn('DIRECT', {})); + } + }; + + handleMove = (dir) => { + const { columnId, dispatch } = this.props; + dispatch(moveColumn(columnId, dir)); + }; + + handleHeaderClick = () => { + this.column.scrollTop(); + }; + + componentDidMount () { + const { dispatch, conversationsMode } = this.props; + + dispatch(mountConversations()); + + if (conversationsMode) { + dispatch(expandConversations()); + } else { + dispatch(expandDirectTimeline()); + } + + this.disconnect = dispatch(connectDirectStream()); + } + + componentDidUpdate(prevProps) { + const { dispatch, conversationsMode } = this.props; + + if (prevProps.conversationsMode && !conversationsMode) { + dispatch(expandDirectTimeline()); + } else if (!prevProps.conversationsMode && conversationsMode) { + dispatch(expandConversations()); + } + } + + componentWillUnmount () { + this.props.dispatch(unmountConversations()); + + if (this.disconnect) { + this.disconnect(); + this.disconnect = null; + } + } + + setRef = c => { + this.column = c; + }; + + handleLoadMoreTimeline = maxId => { + this.props.dispatch(expandDirectTimeline({ maxId })); + }; + + handleLoadMoreConversations = maxId => { + this.props.dispatch(expandConversations({ maxId })); + }; + + render () { + const { intl, hasUnread, columnId, multiColumn, conversationsMode } = this.props; + const pinned = !!columnId; + + let contents; + if (conversationsMode) { + contents = ( + } + emptyMessage={} + /> + ); + } else { + contents = ( + } + emptyMessage={} + /> + ); + } + + return ( + + + + + + {contents} + + + {intl.formatMessage(messages.title)} + + + + ); + } + +} -- cgit