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) => {
|
return (dispatch, getState) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_REPLY,
|
type: COMPOSE_REPLY,
|
||||||
|
@ -64,7 +64,7 @@ export function replyCompose(status, router) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!getState().getIn(['compose', 'mounted'])) {
|
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) => {
|
return (dispatch, getState) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_MENTION,
|
type: COMPOSE_MENTION,
|
||||||
|
@ -89,12 +89,12 @@ export function mentionCompose(account, router) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!getState().getIn(['compose', 'mounted'])) {
|
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) => {
|
return (dispatch, getState) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_DIRECT,
|
type: COMPOSE_DIRECT,
|
||||||
|
@ -102,12 +102,12 @@ export function directCompose(account, router) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!getState().getIn(['compose', 'mounted'])) {
|
if (!getState().getIn(['compose', 'mounted'])) {
|
||||||
router.push('/statuses/new');
|
routerHistory.push('/statuses/new');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function submitCompose() {
|
export function submitCompose(routerHistory) {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
const status = getState().getIn(['compose', 'text'], '');
|
const status = getState().getIn(['compose', 'text'], '');
|
||||||
const media = getState().getIn(['compose', 'media_attachments']);
|
const media = getState().getIn(['compose', 'media_attachments']);
|
||||||
|
@ -133,21 +133,22 @@ export function submitCompose() {
|
||||||
dispatch(insertIntoTagHistory(response.data.tags, status));
|
dispatch(insertIntoTagHistory(response.data.tags, status));
|
||||||
dispatch(submitComposeSuccess({ ...response.data }));
|
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) {
|
if (getState().getIn(['timelines', timelineId, 'items', 0]) !== null) {
|
||||||
dispatch(updateTimeline(timelineId, { ...response.data }));
|
dispatch(updateTimeline(timelineId, { ...response.data }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
insertIfOnline('home');
|
if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0) {
|
||||||
|
routerHistory.push('/timelines/direct');
|
||||||
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
} else if (response.data.visibility !== 'direct') {
|
||||||
|
insertIfOnline('home');
|
||||||
|
} else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
||||||
insertIfOnline('community');
|
insertIfOnline('community');
|
||||||
insertIfOnline('public');
|
insertIfOnline('public');
|
||||||
} else if (response.data.visibility === 'direct') {
|
|
||||||
insertIfOnline('direct');
|
|
||||||
}
|
}
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
dispatch(submitComposeFail(error));
|
dispatch(submitComposeFail(error));
|
||||||
|
|
|
@ -5,11 +5,22 @@ import {
|
||||||
importFetchedStatus,
|
importFetchedStatus,
|
||||||
} from './importer';
|
} 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_REQUEST = 'CONVERSATIONS_FETCH_REQUEST';
|
||||||
export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS';
|
export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS';
|
||||||
export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL';
|
export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL';
|
||||||
export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE';
|
export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE';
|
||||||
|
|
||||||
|
export const mountConversations = () => ({
|
||||||
|
type: CONVERSATIONS_MOUNT,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const unmountConversations = () => ({
|
||||||
|
type: CONVERSATIONS_UNMOUNT,
|
||||||
|
});
|
||||||
|
|
||||||
export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
|
export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
|
||||||
dispatch(expandConversationsRequest());
|
dispatch(expandConversationsRequest());
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@ const messages = defineMessages({
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
class ComposeForm extends ImmutablePureComponent {
|
class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
router: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
text: PropTypes.string.isRequired,
|
text: PropTypes.string.isRequired,
|
||||||
|
@ -84,7 +88,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onSubmit();
|
this.props.onSubmit(this.context.router.history);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSuggestionsClearRequested = () => {
|
onSuggestionsClearRequested = () => {
|
||||||
|
|
|
@ -14,6 +14,10 @@ const messages = defineMessages({
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
class Upload extends ImmutablePureComponent {
|
class Upload extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
router: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
media: ImmutablePropTypes.map.isRequired,
|
media: ImmutablePropTypes.map.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
@ -37,7 +41,7 @@ class Upload extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleSubmit = () => {
|
handleSubmit = () => {
|
||||||
this.handleInputBlur();
|
this.handleInputBlur();
|
||||||
this.props.onSubmit();
|
this.props.onSubmit(this.context.router.history);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUndoClick = () => {
|
handleUndoClick = () => {
|
||||||
|
|
|
@ -33,8 +33,8 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
dispatch(changeCompose(text));
|
dispatch(changeCompose(text));
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit () {
|
onSubmit (router) {
|
||||||
dispatch(submitCompose());
|
dispatch(submitCompose(router));
|
||||||
},
|
},
|
||||||
|
|
||||||
onClearSuggestions () {
|
onClearSuggestions () {
|
||||||
|
|
|
@ -22,8 +22,8 @@ const mapDispatchToProps = dispatch => ({
|
||||||
dispatch(openModal('FOCAL_POINT', { id }));
|
dispatch(openModal('FOCAL_POINT', { id }));
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit () {
|
onSubmit (router) {
|
||||||
dispatch(submitCompose());
|
dispatch(submitCompose(router));
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Column from '../../components/column';
|
import Column from '../../components/column';
|
||||||
import ColumnHeader from '../../components/column_header';
|
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 { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { connectDirectStream } from '../../actions/streaming';
|
import { connectDirectStream } from '../../actions/streaming';
|
||||||
|
@ -48,11 +48,14 @@ class DirectTimeline extends React.PureComponent {
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
|
dispatch(mountConversations());
|
||||||
dispatch(expandConversations());
|
dispatch(expandConversations());
|
||||||
this.disconnect = dispatch(connectDirectStream());
|
this.disconnect = dispatch(connectDirectStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
|
this.props.dispatch(unmountConversations());
|
||||||
|
|
||||||
if (this.disconnect) {
|
if (this.disconnect) {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
this.disconnect = null;
|
this.disconnect = null;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
import {
|
import {
|
||||||
|
CONVERSATIONS_MOUNT,
|
||||||
|
CONVERSATIONS_UNMOUNT,
|
||||||
CONVERSATIONS_FETCH_REQUEST,
|
CONVERSATIONS_FETCH_REQUEST,
|
||||||
CONVERSATIONS_FETCH_SUCCESS,
|
CONVERSATIONS_FETCH_SUCCESS,
|
||||||
CONVERSATIONS_FETCH_FAIL,
|
CONVERSATIONS_FETCH_FAIL,
|
||||||
|
@ -11,6 +13,7 @@ const initialState = ImmutableMap({
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
hasMore: true,
|
hasMore: true,
|
||||||
|
mounted: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const conversationToMap = item => ImmutableMap({
|
const conversationToMap = item => ImmutableMap({
|
||||||
|
@ -73,6 +76,10 @@ export default function conversations(state = initialState, action) {
|
||||||
return expandNormalizedConversations(state, action.conversations, action.next);
|
return expandNormalizedConversations(state, action.conversations, action.next);
|
||||||
case CONVERSATIONS_UPDATE:
|
case CONVERSATIONS_UPDATE:
|
||||||
return updateConversation(state, action.conversation);
|
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:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ class BatchedRemoveStatusService < BaseService
|
||||||
# Cannot be batched
|
# Cannot be batched
|
||||||
statuses.each do |status|
|
statuses.each do |status|
|
||||||
unpush_from_public_timelines(status)
|
unpush_from_public_timelines(status)
|
||||||
unpush_from_direct_timelines(status) if status.direct_visibility?
|
|
||||||
batch_salmon_slaps(status) if status.local?
|
batch_salmon_slaps(status) if status.local?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -96,16 +95,6 @@ class BatchedRemoveStatusService < BaseService
|
||||||
end
|
end
|
||||||
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)
|
def batch_salmon_slaps(status)
|
||||||
return if @mentions[status.id].empty?
|
return if @mentions[status.id].empty?
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,12 @@ class FanOutOnWriteService < BaseService
|
||||||
def call(status)
|
def call(status)
|
||||||
raise Mastodon::RaceConditionError if status.visibility.nil?
|
raise Mastodon::RaceConditionError if status.visibility.nil?
|
||||||
|
|
||||||
deliver_to_self(status) if status.account.local?
|
|
||||||
|
|
||||||
render_anonymous_payload(status)
|
render_anonymous_payload(status)
|
||||||
|
|
||||||
if status.direct_visibility?
|
if status.direct_visibility?
|
||||||
deliver_to_mentioned_followers(status)
|
|
||||||
deliver_to_direct_timelines(status)
|
|
||||||
deliver_to_own_conversation(status)
|
deliver_to_own_conversation(status)
|
||||||
else
|
else
|
||||||
|
deliver_to_self(status) if status.account.local?
|
||||||
deliver_to_followers(status)
|
deliver_to_followers(status)
|
||||||
deliver_to_lists(status)
|
deliver_to_lists(status)
|
||||||
end
|
end
|
||||||
|
@ -56,16 +53,6 @@ class FanOutOnWriteService < BaseService
|
||||||
end
|
end
|
||||||
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)
|
def render_anonymous_payload(status)
|
||||||
@payload = InlineRenderer.render(status, nil, :status)
|
@payload = InlineRenderer.render(status, nil, :status)
|
||||||
@payload = Oj.dump(event: :update, payload: @payload)
|
@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?
|
Redis.current.publish('timeline:public:local:media', @payload) if status.local?
|
||||||
end
|
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)
|
def deliver_to_own_conversation(status)
|
||||||
AccountConversation.add_status(status.account, status)
|
AccountConversation.add_status(status.account, status)
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,7 +21,6 @@ class RemoveStatusService < BaseService
|
||||||
remove_from_hashtags
|
remove_from_hashtags
|
||||||
remove_from_public
|
remove_from_public
|
||||||
remove_from_media if status.media_attachments.any?
|
remove_from_media if status.media_attachments.any?
|
||||||
remove_from_direct if status.direct_visibility?
|
|
||||||
|
|
||||||
@status.destroy!
|
@status.destroy!
|
||||||
|
|
||||||
|
@ -153,13 +152,6 @@ class RemoveStatusService < BaseService
|
||||||
Redis.current.publish('timeline:public:local:media', @payload) if @status.local?
|
Redis.current.publish('timeline:public:local:media', @payload) if @status.local?
|
||||||
end
|
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
|
def redis
|
||||||
Redis.current
|
Redis.current
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue