diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2016-11-23 22:57:57 +0100 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2016-11-23 22:57:57 +0100 |
commit | 7cee27f51790617859da87c7aef432373b40aad4 (patch) | |
tree | 68bec6934312f7155faddc96f4b77473ba9a8205 /app/assets | |
parent | 3373ae02ded0ac5847350da9f9550721cdebe732 (diff) |
Fix unfollows not clearing reblogs, fix blocks not clearing reblogs and notifications,
skip ActionCable for follow/unfollow/block events, instead clear UI from blocked account's posts instantly if block request succeeds. Add forgotten i18n for sensitive content
Diffstat (limited to 'app/assets')
10 files changed, 72 insertions, 19 deletions
diff --git a/app/assets/javascripts/components/actions/accounts.jsx b/app/assets/javascripts/components/actions/accounts.jsx index 4a0777a64..759435afe 100644 --- a/app/assets/javascripts/components/actions/accounts.jsx +++ b/app/assets/javascripts/components/actions/accounts.jsx @@ -246,7 +246,8 @@ export function blockAccount(id) { dispatch(blockAccountRequest(id)); api(getState).post(`/api/v1/accounts/${id}/block`).then(response => { - dispatch(blockAccountSuccess(response.data)); + // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers + dispatch(blockAccountSuccess(response.data, getState().get('statuses'))); }).catch(error => { dispatch(blockAccountFail(id, error)); }); @@ -272,10 +273,11 @@ export function blockAccountRequest(id) { }; }; -export function blockAccountSuccess(relationship) { +export function blockAccountSuccess(relationship, statuses) { return { type: ACCOUNT_BLOCK_SUCCESS, - relationship + relationship, + statuses }; }; diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx index bf851e5bf..603561ab3 100644 --- a/app/assets/javascripts/components/components/status.jsx +++ b/app/assets/javascripts/components/components/status.jsx @@ -34,6 +34,7 @@ const Status = React.createClass({ onReblog: React.PropTypes.func, onDelete: React.PropTypes.func, onOpenMedia: React.PropTypes.func, + onBlock: React.PropTypes.func, me: React.PropTypes.number, muted: React.PropTypes.bool }, diff --git a/app/assets/javascripts/components/components/status_action_bar.jsx b/app/assets/javascripts/components/components/status_action_bar.jsx index dec1decff..35feda88b 100644 --- a/app/assets/javascripts/components/components/status_action_bar.jsx +++ b/app/assets/javascripts/components/components/status_action_bar.jsx @@ -7,6 +7,7 @@ import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, mention: { id: 'status.mention', defaultMessage: 'Mention' }, + block: { id: 'account.block', defaultMessage: 'Block' }, reply: { id: 'status.reply', defaultMessage: 'Reply' }, reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, favourite: { id: 'status.favourite', defaultMessage: 'Favourite' } @@ -24,7 +25,8 @@ const StatusActionBar = React.createClass({ onFavourite: React.PropTypes.func, onReblog: React.PropTypes.func, onDelete: React.PropTypes.func, - onMention: React.PropTypes.func + onMention: React.PropTypes.func, + onBlock: React.PropTypes.func }, mixins: [PureRenderMixin], @@ -49,6 +51,10 @@ const StatusActionBar = React.createClass({ this.props.onMention(this.props.status.get('account')); }, + handleBlockClick () { + this.props.onBlock(this.props.status.get('account')); + }, + render () { const { status, me, intl } = this.props; let menu = []; @@ -57,6 +63,7 @@ const StatusActionBar = React.createClass({ menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); } else { menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick }); + menu.push({ text: intl.formatMessage(messages.block), action: this.handleBlockClick }); } return ( diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index 87c7c65f3..c9f037ec2 100644 --- a/app/assets/javascripts/components/containers/mastodon.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -75,11 +75,6 @@ const Mastodon = React.createClass({ return store.dispatch(updateTimeline(data.timeline, JSON.parse(data.message))); case 'delete': return store.dispatch(deleteFromTimelines(data.id)); - case 'merge': - case 'unmerge': - return store.dispatch(refreshTimeline('home', true)); - case 'block': - return store.dispatch(refreshTimeline('mentions', true)); case 'notification': return store.dispatch(updateNotifications(JSON.parse(data.message), getMessagesForLocale(locale), locale)); } diff --git a/app/assets/javascripts/components/containers/status_container.jsx b/app/assets/javascripts/components/containers/status_container.jsx index 28756b5ef..6a882eab4 100644 --- a/app/assets/javascripts/components/containers/status_container.jsx +++ b/app/assets/javascripts/components/containers/status_container.jsx @@ -1,18 +1,19 @@ -import { connect } from 'react-redux'; -import Status from '../components/status'; +import { connect } from 'react-redux'; +import Status from '../components/status'; import { makeGetStatus } from '../selectors'; import { replyCompose, mentionCompose -} from '../actions/compose'; +} from '../actions/compose'; import { reblog, favourite, unreblog, unfavourite -} from '../actions/interactions'; -import { deleteStatus } from '../actions/statuses'; -import { openMedia } from '../actions/modal'; +} from '../actions/interactions'; +import { blockAccount } from '../actions/accounts'; +import { deleteStatus } from '../actions/statuses'; +import { openMedia } from '../actions/modal'; import { createSelector } from 'reselect' const mapStateToProps = (state, props) => ({ @@ -91,6 +92,10 @@ const mapDispatchToProps = (dispatch) => ({ onOpenMedia (url) { dispatch(openMedia(url)); + }, + + onBlock (account) { + dispatch(blockAccount(account.get('id'))); } }); diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 7c42e481d..5ad1ca172 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -8,7 +8,7 @@ import Autosuggest from 'react-autosuggest'; import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container'; import { debounce } from 'react-decoration'; import UploadButtonContainer from '../containers/upload_button_container'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import Toggle from 'react-toggle'; const messages = defineMessages({ @@ -188,7 +188,7 @@ const ComposeForm = React.createClass({ <label style={{ display: 'block', lineHeight: '24px', verticalAlign: 'middle', marginTop: '10px', borderTop: '1px solid #616b86', paddingTop: '10px' }}> <Toggle checked={this.props.sensitive} onChange={this.handleChangeSensitivity} /> - <span style={{ display: 'inline-block', verticalAlign: 'middle', marginBottom: '14px', marginLeft: '8px', color: '#9baec8' }}>Sensitive content</span> + <span style={{ display: 'inline-block', verticalAlign: 'middle', marginBottom: '14px', marginLeft: '8px', color: '#9baec8' }}><FormattedMessage id='compose_form.sensitive' defaultMessage='Mark content as sensitive' /></span> </label> </div> ); diff --git a/app/assets/javascripts/components/locales/en.jsx b/app/assets/javascripts/components/locales/en.jsx index f3326bf90..0ea324f66 100644 --- a/app/assets/javascripts/components/locales/en.jsx +++ b/app/assets/javascripts/components/locales/en.jsx @@ -8,6 +8,8 @@ const en = { "status.reblog": "Reblog", "status.favourite": "Favourite", "status.reblogged_by": "{name} reblogged", + "status.sensitive_warning": "Sensitive content", + "status.sensitive_toggle": "Click to view", "video_player.toggle_sound": "Toggle sound", "account.mention": "Mention", "account.edit_profile": "Edit profile", @@ -35,6 +37,7 @@ const en = { "tabs_bar.notifications": "Notifications", "compose_form.placeholder": "What is on your mind?", "compose_form.publish": "Toot", + "compose_form.sensitive": "Mark content as sensitive", "navigation_bar.settings": "Settings", "navigation_bar.public_timeline": "Public timeline", "navigation_bar.logout": "Logout", diff --git a/app/assets/javascripts/components/reducers/notifications.jsx b/app/assets/javascripts/components/reducers/notifications.jsx index 0e67e732a..617a833d2 100644 --- a/app/assets/javascripts/components/reducers/notifications.jsx +++ b/app/assets/javascripts/components/reducers/notifications.jsx @@ -3,6 +3,7 @@ import { NOTIFICATIONS_REFRESH_SUCCESS, NOTIFICATIONS_EXPAND_SUCCESS } from '../actions/notifications'; +import { ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts'; import Immutable from 'immutable'; const initialState = Immutable.Map({ @@ -43,6 +44,10 @@ const appendNormalizedNotifications = (state, notifications, next) => { return state.update('items', list => list.push(...items)).set('next', next); }; +const filterNotifications = (state, relationship) => { + return state.update('items', list => list.filterNot(item => item.get('account') === relationship.id)); +}; + export default function notifications(state = initialState, action) { switch(action.type) { case NOTIFICATIONS_UPDATE: @@ -51,6 +56,8 @@ export default function notifications(state = initialState, action) { return normalizeNotifications(state, action.notifications, action.next); case NOTIFICATIONS_EXPAND_SUCCESS: return appendNormalizedNotifications(state, action.notifications, action.next); + case ACCOUNT_BLOCK_SUCCESS: + return filterNotifications(state, action.relationship); default: return state; } diff --git a/app/assets/javascripts/components/reducers/statuses.jsx b/app/assets/javascripts/components/reducers/statuses.jsx index 2a24a75e4..f42b1a481 100644 --- a/app/assets/javascripts/components/reducers/statuses.jsx +++ b/app/assets/javascripts/components/reducers/statuses.jsx @@ -16,7 +16,8 @@ import { } from '../actions/timelines'; import { ACCOUNT_TIMELINE_FETCH_SUCCESS, - ACCOUNT_TIMELINE_EXPAND_SUCCESS + ACCOUNT_TIMELINE_EXPAND_SUCCESS, + ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts'; import { NOTIFICATIONS_UPDATE, @@ -56,6 +57,18 @@ const deleteStatus = (state, id, references) => { return state.delete(id); }; +const filterStatuses = (state, relationship) => { + state.forEach(status => { + if (status.get('account') !== relationship.id) { + return; + } + + state = deleteStatus(state, status.get('id'), state.filter(item => item.get('reblog') === status.get('id'))); + }); + + return state; +}; + const initialState = Immutable.Map(); export default function statuses(state = initialState, action) { @@ -79,6 +92,8 @@ export default function statuses(state = initialState, action) { return normalizeStatuses(state, action.statuses); case TIMELINE_DELETE: return deleteStatus(state, action.id, action.references); + case ACCOUNT_BLOCK_SUCCESS: + return filterStatuses(state, action.relationship); default: return state; } diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx index 9e79a4100..358734eaf 100644 --- a/app/assets/javascripts/components/reducers/timelines.jsx +++ b/app/assets/javascripts/components/reducers/timelines.jsx @@ -13,7 +13,8 @@ import { import { ACCOUNT_FETCH_SUCCESS, ACCOUNT_TIMELINE_FETCH_SUCCESS, - ACCOUNT_TIMELINE_EXPAND_SUCCESS + ACCOUNT_TIMELINE_EXPAND_SUCCESS, + ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts'; import { STATUS_FETCH_SUCCESS, @@ -140,6 +141,21 @@ const deleteStatus = (state, id, accountId, references) => { return state; }; +const filterTimelines = (state, relationship, statuses) => { + let references; + + statuses.forEach(status => { + if (status.get('account') !== relationship.id) { + return; + } + + references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => [item.get('id'), item.get('account')]); + state = deleteStatus(state, status.get('id'), status.get('account'), references); + }); + + return state; +}; + const normalizeContext = (state, id, ancestors, descendants) => { const ancestorsIds = ancestors.map(ancestor => ancestor.get('id')); const descendantsIds = descendants.map(descendant => descendant.get('id')); @@ -166,6 +182,8 @@ export default function timelines(state = initialState, action) { return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses), action.replace); case ACCOUNT_TIMELINE_EXPAND_SUCCESS: return appendNormalizedAccountTimeline(state, action.id, Immutable.fromJS(action.statuses)); + case ACCOUNT_BLOCK_SUCCESS: + return filterTimelines(state, action.relationship, action.statuses); default: return state; } |