Do not push DMs into the home feed (#8940)
* Do not push DMs into the home feed * Show DMs column after sending a DM, if DMs column is not already shown
This commit is contained in:
		
							parent
							
								
									790d3bc637
								
							
						
					
					
						commit
						87fdd139b8
					
				
					 11 changed files with 52 additions and 64 deletions
				
			
		|  | @ -56,7 +56,7 @@ export function changeCompose(text) { | |||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function replyCompose(status, router) { | ||||
| export function replyCompose(status, routerHistory) { | ||||
|   return (dispatch, getState) => { | ||||
|     dispatch({ | ||||
|       type: COMPOSE_REPLY, | ||||
|  | @ -64,7 +64,7 @@ export function replyCompose(status, router) { | |||
|     }); | ||||
| 
 | ||||
|     if (!getState().getIn(['compose', 'mounted'])) { | ||||
|       router.push('/statuses/new'); | ||||
|       routerHistory.push('/statuses/new'); | ||||
|     } | ||||
|   }; | ||||
| }; | ||||
|  | @ -81,7 +81,7 @@ export function resetCompose() { | |||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function mentionCompose(account, router) { | ||||
| export function mentionCompose(account, routerHistory) { | ||||
|   return (dispatch, getState) => { | ||||
|     dispatch({ | ||||
|       type: COMPOSE_MENTION, | ||||
|  | @ -89,12 +89,12 @@ export function mentionCompose(account, router) { | |||
|     }); | ||||
| 
 | ||||
|     if (!getState().getIn(['compose', 'mounted'])) { | ||||
|       router.push('/statuses/new'); | ||||
|       routerHistory.push('/statuses/new'); | ||||
|     } | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function directCompose(account, router) { | ||||
| export function directCompose(account, routerHistory) { | ||||
|   return (dispatch, getState) => { | ||||
|     dispatch({ | ||||
|       type: COMPOSE_DIRECT, | ||||
|  | @ -102,12 +102,12 @@ export function directCompose(account, router) { | |||
|     }); | ||||
| 
 | ||||
|     if (!getState().getIn(['compose', 'mounted'])) { | ||||
|       router.push('/statuses/new'); | ||||
|       routerHistory.push('/statuses/new'); | ||||
|     } | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function submitCompose() { | ||||
| export function submitCompose(routerHistory) { | ||||
|   return function (dispatch, getState) { | ||||
|     const status = getState().getIn(['compose', 'text'], ''); | ||||
|     const media  = getState().getIn(['compose', 'media_attachments']); | ||||
|  | @ -133,21 +133,22 @@ export function submitCompose() { | |||
|       dispatch(insertIntoTagHistory(response.data.tags, status)); | ||||
|       dispatch(submitComposeSuccess({ ...response.data })); | ||||
| 
 | ||||
|       // To make the app more responsive, immediately get the status into the columns
 | ||||
|       // To make the app more responsive, immediately push the status
 | ||||
|       // into the columns
 | ||||
| 
 | ||||
|       const insertIfOnline = (timelineId) => { | ||||
|       const insertIfOnline = timelineId => { | ||||
|         if (getState().getIn(['timelines', timelineId, 'items', 0]) !== null) { | ||||
|           dispatch(updateTimeline(timelineId, { ...response.data })); | ||||
|         } | ||||
|       }; | ||||
| 
 | ||||
|       insertIfOnline('home'); | ||||
| 
 | ||||
|       if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { | ||||
|       if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0) { | ||||
|         routerHistory.push('/timelines/direct'); | ||||
|       } else if (response.data.visibility !== 'direct') { | ||||
|         insertIfOnline('home'); | ||||
|       } else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { | ||||
|         insertIfOnline('community'); | ||||
|         insertIfOnline('public'); | ||||
|       } else if (response.data.visibility === 'direct') { | ||||
|         insertIfOnline('direct'); | ||||
|       } | ||||
|     }).catch(function (error) { | ||||
|       dispatch(submitComposeFail(error)); | ||||
|  |  | |||
|  | @ -5,11 +5,22 @@ import { | |||
|   importFetchedStatus, | ||||
| } from './importer'; | ||||
| 
 | ||||
| export const CONVERSATIONS_MOUNT   = 'CONVERSATIONS_MOUNT'; | ||||
| export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT'; | ||||
| 
 | ||||
| export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST'; | ||||
| export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS'; | ||||
| export const CONVERSATIONS_FETCH_FAIL    = 'CONVERSATIONS_FETCH_FAIL'; | ||||
| export const CONVERSATIONS_UPDATE        = 'CONVERSATIONS_UPDATE'; | ||||
| 
 | ||||
| export const mountConversations = () => ({ | ||||
|   type: CONVERSATIONS_MOUNT, | ||||
| }); | ||||
| 
 | ||||
| export const unmountConversations = () => ({ | ||||
|   type: CONVERSATIONS_UNMOUNT, | ||||
| }); | ||||
| 
 | ||||
| export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => { | ||||
|   dispatch(expandConversationsRequest()); | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,6 +30,10 @@ const messages = defineMessages({ | |||
| export default @injectIntl | ||||
| class ComposeForm extends ImmutablePureComponent { | ||||
| 
 | ||||
|   static contextTypes = { | ||||
|     router: PropTypes.object, | ||||
|   }; | ||||
| 
 | ||||
|   static propTypes = { | ||||
|     intl: PropTypes.object.isRequired, | ||||
|     text: PropTypes.string.isRequired, | ||||
|  | @ -84,7 +88,7 @@ class ComposeForm extends ImmutablePureComponent { | |||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     this.props.onSubmit(); | ||||
|     this.props.onSubmit(this.context.router.history); | ||||
|   } | ||||
| 
 | ||||
|   onSuggestionsClearRequested = () => { | ||||
|  |  | |||
|  | @ -14,6 +14,10 @@ const messages = defineMessages({ | |||
| export default @injectIntl | ||||
| class Upload extends ImmutablePureComponent { | ||||
| 
 | ||||
|   static contextTypes = { | ||||
|     router: PropTypes.object, | ||||
|   }; | ||||
| 
 | ||||
|   static propTypes = { | ||||
|     media: ImmutablePropTypes.map.isRequired, | ||||
|     intl: PropTypes.object.isRequired, | ||||
|  | @ -37,7 +41,7 @@ class Upload extends ImmutablePureComponent { | |||
| 
 | ||||
|   handleSubmit = () => { | ||||
|     this.handleInputBlur(); | ||||
|     this.props.onSubmit(); | ||||
|     this.props.onSubmit(this.context.router.history); | ||||
|   } | ||||
| 
 | ||||
|   handleUndoClick = () => { | ||||
|  |  | |||
|  | @ -33,8 +33,8 @@ const mapDispatchToProps = (dispatch) => ({ | |||
|     dispatch(changeCompose(text)); | ||||
|   }, | ||||
| 
 | ||||
|   onSubmit () { | ||||
|     dispatch(submitCompose()); | ||||
|   onSubmit (router) { | ||||
|     dispatch(submitCompose(router)); | ||||
|   }, | ||||
| 
 | ||||
|   onClearSuggestions () { | ||||
|  |  | |||
|  | @ -22,8 +22,8 @@ const mapDispatchToProps = dispatch => ({ | |||
|     dispatch(openModal('FOCAL_POINT', { id })); | ||||
|   }, | ||||
| 
 | ||||
|   onSubmit () { | ||||
|     dispatch(submitCompose()); | ||||
|   onSubmit (router) { | ||||
|     dispatch(submitCompose(router)); | ||||
|   }, | ||||
| 
 | ||||
| }); | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import { connect } from 'react-redux'; | |||
| import PropTypes from 'prop-types'; | ||||
| import Column from '../../components/column'; | ||||
| import ColumnHeader from '../../components/column_header'; | ||||
| import { expandConversations } from '../../actions/conversations'; | ||||
| import { mountConversations, unmountConversations, expandConversations } from '../../actions/conversations'; | ||||
| import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; | ||||
| import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | ||||
| import { connectDirectStream } from '../../actions/streaming'; | ||||
|  | @ -48,11 +48,14 @@ class DirectTimeline extends React.PureComponent { | |||
|   componentDidMount () { | ||||
|     const { dispatch } = this.props; | ||||
| 
 | ||||
|     dispatch(mountConversations()); | ||||
|     dispatch(expandConversations()); | ||||
|     this.disconnect = dispatch(connectDirectStream()); | ||||
|   } | ||||
| 
 | ||||
|   componentWillUnmount () { | ||||
|     this.props.dispatch(unmountConversations()); | ||||
| 
 | ||||
|     if (this.disconnect) { | ||||
|       this.disconnect(); | ||||
|       this.disconnect = null; | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; | ||||
| import { | ||||
|   CONVERSATIONS_MOUNT, | ||||
|   CONVERSATIONS_UNMOUNT, | ||||
|   CONVERSATIONS_FETCH_REQUEST, | ||||
|   CONVERSATIONS_FETCH_SUCCESS, | ||||
|   CONVERSATIONS_FETCH_FAIL, | ||||
|  | @ -11,6 +13,7 @@ const initialState = ImmutableMap({ | |||
|   items: ImmutableList(), | ||||
|   isLoading: false, | ||||
|   hasMore: true, | ||||
|   mounted: false, | ||||
| }); | ||||
| 
 | ||||
| const conversationToMap = item => ImmutableMap({ | ||||
|  | @ -73,6 +76,10 @@ export default function conversations(state = initialState, action) { | |||
|     return expandNormalizedConversations(state, action.conversations, action.next); | ||||
|   case CONVERSATIONS_UPDATE: | ||||
|     return updateConversation(state, action.conversation); | ||||
|   case CONVERSATIONS_MOUNT: | ||||
|     return state.update('mounted', count => count + 1); | ||||
|   case CONVERSATIONS_UNMOUNT: | ||||
|     return state.update('mounted', count => count - 1); | ||||
|   default: | ||||
|     return state; | ||||
|   } | ||||
|  |  | |||
|  | @ -39,7 +39,6 @@ class BatchedRemoveStatusService < BaseService | |||
|     # Cannot be batched | ||||
|     statuses.each do |status| | ||||
|       unpush_from_public_timelines(status) | ||||
|       unpush_from_direct_timelines(status) if status.direct_visibility? | ||||
|       batch_salmon_slaps(status) if status.local? | ||||
|     end | ||||
| 
 | ||||
|  | @ -96,16 +95,6 @@ class BatchedRemoveStatusService < BaseService | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def unpush_from_direct_timelines(status) | ||||
|     payload = @json_payloads[status.id] | ||||
|     redis.pipelined do | ||||
|       @mentions[status.id].each do |mention| | ||||
|         redis.publish("timeline:direct:#{mention.account.id}", payload) if mention.account.local? | ||||
|       end | ||||
|       redis.publish("timeline:direct:#{status.account.id}", payload) if status.account.local? | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def batch_salmon_slaps(status) | ||||
|     return if @mentions[status.id].empty? | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,15 +6,12 @@ class FanOutOnWriteService < BaseService | |||
|   def call(status) | ||||
|     raise Mastodon::RaceConditionError if status.visibility.nil? | ||||
| 
 | ||||
|     deliver_to_self(status) if status.account.local? | ||||
| 
 | ||||
|     render_anonymous_payload(status) | ||||
| 
 | ||||
|     if status.direct_visibility? | ||||
|       deliver_to_mentioned_followers(status) | ||||
|       deliver_to_direct_timelines(status) | ||||
|       deliver_to_own_conversation(status) | ||||
|     else | ||||
|       deliver_to_self(status) if status.account.local? | ||||
|       deliver_to_followers(status) | ||||
|       deliver_to_lists(status) | ||||
|     end | ||||
|  | @ -56,16 +53,6 @@ class FanOutOnWriteService < BaseService | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def deliver_to_mentioned_followers(status) | ||||
|     Rails.logger.debug "Delivering status #{status.id} to mentioned followers" | ||||
| 
 | ||||
|     status.mentions.includes(:account).each do |mention| | ||||
|       mentioned_account = mention.account | ||||
|       next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id) | ||||
|       FeedManager.instance.push_to_home(mentioned_account, status) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def render_anonymous_payload(status) | ||||
|     @payload = InlineRenderer.render(status, nil, :status) | ||||
|     @payload = Oj.dump(event: :update, payload: @payload) | ||||
|  | @ -94,16 +81,6 @@ class FanOutOnWriteService < BaseService | |||
|     Redis.current.publish('timeline:public:local:media', @payload) if status.local? | ||||
|   end | ||||
| 
 | ||||
|   def deliver_to_direct_timelines(status) | ||||
|     Rails.logger.debug "Delivering status #{status.id} to direct timelines" | ||||
| 
 | ||||
|     status.mentions.includes(:account).each do |mention| | ||||
|       Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? | ||||
|     end | ||||
| 
 | ||||
|     Redis.current.publish("timeline:direct:#{status.account.id}", @payload) if status.account.local? | ||||
|   end | ||||
| 
 | ||||
|   def deliver_to_own_conversation(status) | ||||
|     AccountConversation.add_status(status.account, status) | ||||
|   end | ||||
|  |  | |||
|  | @ -21,7 +21,6 @@ class RemoveStatusService < BaseService | |||
|     remove_from_hashtags | ||||
|     remove_from_public | ||||
|     remove_from_media if status.media_attachments.any? | ||||
|     remove_from_direct if status.direct_visibility? | ||||
| 
 | ||||
|     @status.destroy! | ||||
| 
 | ||||
|  | @ -153,13 +152,6 @@ class RemoveStatusService < BaseService | |||
|     Redis.current.publish('timeline:public:local:media', @payload) if @status.local? | ||||
|   end | ||||
| 
 | ||||
|   def remove_from_direct | ||||
|     @mentions.each do |mention| | ||||
|       Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local? | ||||
|     end | ||||
|     Redis.current.publish("timeline:direct:#{@account.id}", @payload) if @account.local? | ||||
|   end | ||||
| 
 | ||||
|   def redis | ||||
|     Redis.current | ||||
|   end | ||||
|  |  | |||
		Reference in a new issue