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
remotes/1727458204337373841/tmp_refs/heads/signup-info-prompt
Eugen Rochko 2018-10-11 01:31:03 +02:00 committed by GitHub
parent 790d3bc637
commit 87fdd139b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 52 additions and 64 deletions

View File

@ -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));

View File

@ -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());

View File

@ -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 = () => {

View File

@ -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 = () => {

View File

@ -33,8 +33,8 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(changeCompose(text));
},
onSubmit () {
dispatch(submitCompose());
onSubmit (router) {
dispatch(submitCompose(router));
},
onClearSuggestions () {

View File

@ -22,8 +22,8 @@ const mapDispatchToProps = dispatch => ({
dispatch(openModal('FOCAL_POINT', { id }));
},
onSubmit () {
dispatch(submitCompose());
onSubmit (router) {
dispatch(submitCompose(router));
},
});

View File

@ -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;

View File

@ -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;
}

View File

@ -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?

View File

@ -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

View File

@ -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